Зачем заботиться о процессе загрузки веб-приложения в Tomcat? Я много раз видел диаграмму структуры компонентов Tomcat в предыдущей статье, и я опубликую ее здесь для обзора:
предыдущийАнализ запуска Tomcat 7В серии статей, при запуске Tomcat будет парсить server.xml, инициализировать и запускать соответствующие компоненты один за другим согласно информации каждого сконфигурированного в нем узла (т.е. вызывать их методы init и start соответственно), но просмотрите исходный код Tomcat 7 для Содержимое server.xml соответствует компонентам на всех уровнях, которые были настроены по умолчанию на приведенном выше рисунке, включая сервер, службу, ядро, соединитель, хост и клапан. Компонент Context на рисунке выше на самом деле то, что мы обычно называем веб-приложением, Интересно то, что этот компонент не настроен в server.xml, и когда мы запускаем его по умолчанию, на самом деле есть несколько веб-приложений, к которым можно получить доступ. : Что, черт возьми, здесь происходит?видел раньшеАнализ запросов Tomcat 7Люди в серии статей должны знать, что после того, как браузер отправит запрос на сервер Tomcat, он в конечном итоге найдет соответствующий объект контекста веб-приложения, доступ к которому осуществляется в соответствии с путем URL-адреса в браузере (по умолчаниюorg.apache.catalina.core.StandardContext
экземпляр класса). Например, доступен URL-адресhttp://localhost:8080/
Затем будет отправлено в папку MAP представляет собой корневое веб-приложение, доступ к URLhttp://localhost:8080/docs
, веб-приложение, представленное папкой docs, будет доступно. Итак, можно предположить, что после запуска Tomcat каждый объект контекста, представляющий соответствующее веб-приложение, должен быть создан внутри контейнера.
В этой статье исследуется этот вопрос. существуетПринцип отключения сервера Tomcat 7Как упоминалось в начале, в конфигурации по умолчанию после запуска Tomcat вы увидите, что на самом деле в фоновом режиме работает 6 потоков:
описано в предыдущих статьяхmain
,http-bio-8080-Acceptor-0
,http-bio-8080-AsyncTimeout
,ajp-bio-8009-Acceptor-0
,ajp-bio-8009-AsyncTimeout
, рассказал о роли этих потоков, о том, как они порождают запросы и отвечают на них. Но есть один поток, который не говорит, т.е.ContainerBackgroundProcessor[StandardEngine[Catalina]]
, а загадка вопроса, на который предстоит ответить в этой статье, — в этой ветке.
Давайте сначала посмотрим, как генерируется этот поток. На самом деле, мы можем увидеть некоторые подсказки из названия. Он называется фоновым процессором контейнера и связан с StandardEngine. То же самое верно и для его функции.
Все компоненты контейнера по умолчанию (StandardEngine, StandardHost, StandardContext, StandardWrapper) в Tomcat 7 наследуют родительский класс.org.apache.catalina.core.ContainerBase
Когда сборка контейнера позвонит методу запуска MATTINDINDERNAL их внутри, внутри, как правило, вызывает метод startInternal (кроме стандартного standcontext реализованного класса) родительский класс, такой какorg.apache.catalina.core.StandardEngine
Метод STARTINTERNAL в классе:
super.startInternal()
То есть вызвать родительский классorg.apache.catalina.core.ContainerBase的startInternal
метод, в конце метода:Линия 6 комплектовLifecycleState.STARTING
статус (это опубликуетLifecycle.START_EVENT
событие), роль этой линии будет упомянута позже в этой статье, и пока она не будет указана. Строка 9 вызывает метод threadStart, посмотрите на код метода threadStart:Здесь вы можете видеть, что если два условия предварительной проверки выполняются, поток будет запущен, и имя потока будет начинаться сContainerBackgroundProcessor[
В начале после имени потока берется метод toString объекта, для примера возьмем StandardEngine, см.org.apache.catalina.core.StandardEngine
Реализован метод toString:Вышеизложенное объясняет происхождение этого фонового потока.
Но здесь есть проблема, так как StandardEngine и StandardHost будут вызыватьsuper.startInternal()
метод, согласно конфигурации по умолчанию, фон должен генерировать два фоновых потока, почему только один?
назадorg.apache.catalina.core.ContainerBase
Метод threadStart имеет два условия проверки перед запуском кода потока:
null
, backgroundProcessorDelay — это-1
ноorg.apache.catalina.core.StandardEngine
Сделал небольшую модификацию в собственном конструкторе:Наконец, конструктор устанавливает значение backgroundProcessorDelay родительского класса с помощью-1
изменился на10
, поэтому, когда Tomcat начинает анализировать xml и встречает узел Engine, соответственно будет сгенерирован поток фоновой обработки.
После разговора о создании этого потока фоновой обработки взгляните на то, что делает этот поток, а затем посмотрите на код запуска этого потока:
Итак, этот поток выполнит метод run внутреннего класса ContainerBackgroundProcessor, взгляните на полный код реализации ContainerBackgroundProcessor: После того, как его метод run приостанавливается на некоторое время, вызывается метод processChildren, который делает две вещи: во-первых, вызывает метод backgroundProcess самого компонента-контейнера, но удаляет все компоненты-подконтейнеры компонента-контейнера. компонент-контейнер и вызвать их метод processChildren. Короче говоря, реализация этого потока заключается в периодическом рекурсивном вызове метода backgroundProcess текущего контейнера и всех его подконтейнеров.И этот метод backgroundProcess был реализован внутри ContainerBase:
Этот код не будет объясняться по одному, если подытожить, то это вызов метода backgroundProcess других внутренних компонентов, связанных с контейнером, один за другим. Последняя регистрацияLifecycle.PERIODIC_EVENT
событие.
Выше приведен обзор того, что делает поток фоновой обработки Tomcat 7. В более ранних версиях Tomcat были некоторые вещи фоновой обработки, которые изначально были настроены и запускались в каждом компоненте.В Tomcat 5 вся фоновая обработка была изменена. поделитесь той же темой.
Вернемся к вопросу, на который нужно ответить в этой статье: как веб-приложение загружается в контейнер? В конце метода backgroundProcess класса ContainerBase:
fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
зарегистрирован в контейнереPERIODIC_EVENT
событие. Как упоминалось ранее, по умолчаниюContainerBackgroundProcessor[StandardEngine[Catalina]]
Поток будет периодически (10 секунд по умолчанию) выполнять методы backgroundProcess компонентов контейнера Engine, Host, Context, Wrapper и связанных с ними компонентов, поэтому он также будет периодически публиковатьPERIODIC_EVENT
событие, вот прослушиватель, связанный со StandardHostorg.apache.catalina.startup.HostConfig
:
Когда Tomcat начинает анализировать xml
org.apache.catalina.startup.Catalina
Строка 386 класса:digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"))
В методе addRuleInstances класса HostRuleSet:
В строках с 9 по 12 видно, что все узлы Host добавляют
org.apache.catalina.startup.HostConfig
объект какorg.apache.catalina.core.StandardHost
прослушиватель объектов
В методе lifecycleEvent HostConfig вы можете увидеть ответ, если компонент Host получает публикацию события Lifecycle.PERIODIC_EVENT (если вам непонятен механизм жизненного цикла Tomcat 7, вы можете прочитать его нижеАнализ запуска Tomcat 7 (5) Механизм жизненного цикла и принцип реализации:
Строка 17, если опубликованное событиеPERIODIC_EVENT
Метод проверки будет выполнен. Строка 19, если опубликованное событиеSTART_EVENT
Затем выполните метод запуска. И метод проверки, и метод запуска в конце вызовут метод deployApps(). Давайте посмотрим на реализацию этого метода:Вот код для публикации веб-приложения различными способами.
Ранее в этой статье упоминалось, что по умолчанию компонент будет выпущен при запуске.Lifecycle.START_EVENT
событие (вorg.apache.catalina.core.ContainerBase
Метод startInternal класса является предпоследней строкой), вернемся к методу lifecycleEvent HostConfig, поэтому метод start HostConfig будет выполняться по умолчанию, в конце метода:
if (host.getDeployOnStartup())
deployApps();
Поскольку конфигурация по умолчанию host.getDeployOnStartup() возвращает true , контейнер будет напрямую загружать соответствующее веб-приложение при запуске.
Конечно, если для атрибута deployOnStartup узла Host в server.xml задано значение false, приложение не будет загружено при запуске контейнера, и служба веб-приложения не может быть предоставлена сразу после запуска. Но поскольку упомянутый выше поток фоновой обработки запущен, метод проверки HostConfig будет выполняться периодически:
Если свойство autoDeploy узла Host имеет значение true (настройка по умолчанию — true ), вы можете видеть, что метод проверки также загрузит веб-приложение в конце.