Может ли JAR, совместно используемый двумя веб-приложениями, регистрировать один и тот же файл в Tomcat? - PullRequest
0 голосов
/ 04 октября 2019

Допустим, у нас есть два веб-приложения и экземпляр Tomcat, загружающий общие JAR-файлы (зависимости для обоих приложений) из внешнего каталога (с помощью shared.loader, определенного в catalina.properties). Следовательно, эти зависимости не упаковываются в файлы WAR.

Допустим также, что:

  • Оба веб-приложения зависят от определенного общего файла JAR, в котором используется структура ведения журнала (log4j2на данный момент, но это не обязательно).
  • Оба веб-приложения используют собственную структуру ведения журналов (нам все равно, идентичны они или нет, если все работает как положено), и разные журналыконфигурации.

Мы хотим, чтобы общий JAR-файл надежно регистрировал один и тот же файл, независимо от того, из какого веб-приложения вызываются его методы. Насколько мы понимаем, оба веб-приложения имеют разные контексты журналирования, и наличие двух таких контекстов регистрирует в одном файле либо невозможно, либо, по крайней мере, опасно. Если это не так или не обязательно должно быть правдой, уточните.

Вопрос : возможно ли достичь описанного выше сценария с помощью единого контекста ведения журнала? Если да, не могли бы вы привести пример, чтобы заставить его работать (критических битов вполне хватит), используя lo4j2 или logback? Есть ли какие-нибудь ловушки?

Обратите внимание, что мы хотели бы избежать установки специального сервлета в одном из веб-приложений для этого (поэтому другое веб-приложение будет вызывать его вместо входа непосредственно вфайл). Использование (например) системного журнала вместо этого может быть решением, но, тем не менее, давайте сосредоточим этот вопрос на описанном сценарии, пожалуйста.

1 Ответ

0 голосов
/ 25 октября 2019

После некоторых исследований, проб и ошибок нам удалось удовлетворить наши требования:

  • Каждое веб-приложение регистрирует свои собственные файлы.
  • Общий JAR всегда регистрирует свои собственныефайл тоже.

По крайней мере, с Log4j2, проблема, кажется, вращается вокруг загрузчиков классов. В нашем случае классы из общего JAR-файла и всех его зависимостей всегда загружались с использованием загрузчика классов, выделенного для (shared.loader). Это означает, что JAR-файлы Log4j2 должны находиться рядом с общим JAR-файлом, и если бы мы попытались удалить их, мы увидели бы ClassNotFoundExceptions.

Теперь мы можем перейти к веб-приложениям:

  1. Если веб-приложение НЕ упаковывает Log4j2 для собственного использования, его средства ведения журнала также загружаются с использованием загрузчика классов для shared.loader (в качестве запасного варианта), а конфигурация ведения журнала веб-приложения перезаписываетКонфигурация применялась ранее (в нашем случае нам пришлось вызывать явную инициализацию или реконфигурацию, вот почему). Это не будет работать должным образом.
  2. Если веб-приложение DOES упаковывает Log4j2 для собственного использования, его регистраторы загружаются с использованием загрузчика классов для веб-приложения (поскольку зависимости упакованы в WEB-INF имеет приоритет), что является совершенно другим «контекстом» (загрузчиком классов), чем в подходе № 1, и конфигурация ведения журнала веб-приложения НЕ перезаписывает ранее примененные конфигурации (поскольку общий JAR и все веб-приложения имеют свой собственный «контекст»').

Это поведение, которое мы наблюдали. Во время подхода # 1 каждое веб-приложение перезаписывало конфигурацию журналирования для приложений, инициализированных / запущенных ранее, потому что «контекст» Log4j2 (загрузчик классов) был общим. Во время подхода # 2 общий контекст JAR Log4j2 был инициализирован веб-приложением, которое вызвало его инициализацию (только один из них), и с тех пор конфигурация не затрагивалась. В нашем случае файл конфигурации был предоставлен веб-приложением (он не был упакован в совместно используемый JAR). Обратите внимание, что на практике одно из веб-приложений всегда должно инициализировать совместно используемый JAR, неявно или явно.

Для абсолютной уверенности мы перечислили дескрипторы открытых файлов в файлах журналов совместно используемого JAR и с подходом № 2Там был действительно только один. При подходе №2 все еще может быть открыто несколько дескрипторов, если некоторые из файлов конфигурации веб-приложений также ссылаются на файлы журналов общего JAR-файла (дублирование конфигурации). Именно такой ситуации вы обычно хотели бы избежать.

Подводные камни, которые мы обнаружили:

  1. Обратите внимание, что замечание shared JAR's Log4j2 context was initialized by the web application that called its initialization (only one of them) немного утомительно. Если мы не копируем или не включаем конфигурацию общего JAR-файла в конфигурацию каждого веб-приложения (и по вышеуказанным причинам мы хотим этого избежать), некоторые из сообщений журнала могут закончиться в другом месте или потеряться во время запуска контейнера сервлета. В целом, может быть невозможно гарантировать порядок запуска веб-приложений. Я могу ошибаться, но из того, что я увидел в журналах Tomcat, Tomcat запускает веб-приложения (файлы WAR) в алфавитном порядке.
  2. Если совместно используемый JAR и какое-либо из веб-приложений имеют некоторые общие зависимости (помимо каркаса ведения журнала), эти зависимости также должны быть помещены в shared.loader. Но, если конфигурация журналирования общего JAR перенаправляет сообщения регистрации любой из этих зависимостей в свои собственные журналы, они не могут попасть в журналы веб-приложения, если только эта зависимость не упакована в веб-приложении (тот же принцип, что и в подходе № 2 выше). ). Но на практике разделение логирования API и вспомогательных реализаций затрудняет это. Например, вы можете прочитать здесь, в StackOverflow, что выбор привязок SLF4J довольно «случайный» (зависит от JVM). Если вы поместите различные привязки в shared.loader и в одну из папок WEB-INF веб-приложения, у вас может не быть уверенности в том, какая привязка будет выбрана.

Я, конечно, не могу рекомендоватьСценарий, который мы пытаемся реализовать, но описанное «решение» определенно работает, как и ожидалось (несмотря на подводные камни).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...