Tomcat

Apache Tomcat — web-server и Jakarta Servlet container. Он принимает сетевые соединения, создаёт servlet request/response, управляет web-приложением и вызывает его servlet-компоненты.

Tomcat работает постоянно после запуска, а не только в момент запроса. Потоки и служебные компоненты ожидают соединения, выполняют фоновые задачи и управляют жизненным циклом приложений.

Основные компоненты

  • Coyote — connectors и HTTP/AJP-взаимодействие;
  • Catalina — servlet container, lifecycle и маршрутизация внутри web-приложения;
  • Jasper — компиляция JSP в servlet;
  • Engine / Host / Context / Wrapper — иерархия контейнеров от виртуального хоста до servlet.

Упрощённый путь:

flowchart LR
    A["TCP connection"] --> B["Coyote Connector"]
    B --> C["Engine / Host"]
    C --> D["Context: web application"]
    D --> E["Filter chain"]
    E --> F["Servlet"]
    F --> B

В Spring MVC servlet — это обычно DispatcherServlet.

Потоковая модель

Для обычного blocking request connector выдаёт worker thread из пула. Поток занят, пока приложение читает запрос, ждёт БД/HTTP и формирует ответ.

Если внешняя зависимость зависла, растёт число занятых threads, затем очередь и latency. Поэтому согласуют:

  • maxThreads и очередь соединений;
  • connection/read/write timeouts;
  • размер JDBC/HTTP connection pools;
  • лимиты request body и headers;
  • timeout внешних вызовов.

Большой thread pool не лечит медленную зависимость: он может лишь создать больше одновременной нагрузки и расхода памяти.

Жизненный цикл приложения

Tomcat создаёт ServletContext, регистрирует listeners, filters и servlets, затем переводит context в рабочее состояние. При остановке вызывает lifecycle callbacks и должен дать приложению закрыть пулы, executors и клиенты.

Если web-приложение создаёт non-daemon thread и не завершает его, redeploy может оставить classloader и вызвать утечку памяти.

Внешний и embedded Tomcat

Классический вариант: собрать WAR и развернуть в установленный Tomcat.

Spring Boot чаще упаковывает Tomcat внутрь executable JAR:

public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
}

Это тот же servlet container, но конфигурацией и lifecycle управляет приложение. Для замены на другой embedded server меняют starter и проверяют совместимость API/настроек.

HTTP и TLS

Connector может завершать TLS сам, но в production TLS часто завершается на reverse proxy или ingress. Тогда Tomcat получает внутренний HTTP и должен доверять forwarded headers только от известного proxy.

Если TLS настроен в Tomcat, keystore должен содержать private key и цепочку сертификатов. См. SSL.

Диагностика

  • thread dump показывает занятые worker threads и место ожидания;
  • access log помогает связать path, status, duration и объём;
  • JMX/метрики показывают active threads, queue и connections;
  • heap dump помогает искать удержанный classloader после redeploy;
  • логи запуска показывают конфликт port и ошибки deployment.

На собеседовании

Tomcat — полноценный Jakarta EE server? Нет. Он прежде всего реализует servlet/web-спецификации; дополнительные enterprise-возможности требуют библиотек или другого runtime.

Чем connector отличается от servlet? Connector работает с сетью и HTTP, container маршрутизирует запрос, servlet реализует обработку на уровне приложения.

Связанные заметки: Сервлет, MVC, Spring Boot, Http протокол.