Tomcat перестает отвечать на запросы JK

У меня неприятная проблема с загружаемыми по нагрузке серверами Tomcat, которые висят. Любая помощь будет принята с благодарностью.

Система

Я запускаю Tomcat 6.0.26 на HotSpot Server 14.3-b01 (Java 1.6.0_17-b04) на трех серверах, сидящих за другим сервером, который действует как балансировщик нагрузки. Балансировщик нагрузки запускает Apache (2.2.8-1) + MOD_JK (1.2.25). На всех серверах работает Ubuntu 8.04.

В Tomcat установлены два коннектора: один AJP и один HTTP. AJP должен использоваться с балансировщиком нагрузки, в то время как HTTP используется командой dev для прямого подключения к выбранному серверу (если у нас есть причина для этого).

У меня есть Lambda Probe 1.7b, установленный на серверах Tomcat, чтобы помочь мне быстро диагностировать и исправить проблему.

Проблема

Здесь проблема: примерно через 1 день сервер приложений завершен, JK Status Manager начинает отчет о статусе ERR для, скажем, Tomcat2. Он просто застрянет в этом состоянии, и единственное исправление, которое я нашел до сих пор, - это ssh box и перезапустить Tomcat.

Я должен также упомянуть, что JK Status Manager занимает намного больше времени, чтобы обновить, когда в этом состоянии сервер Tomcat.

Наконец, подсчет "Занято" застрявшего Tomcat в JK Status Manager всегда высок и не будет снижаться сам по себе - я должен перезапустить сервер Tomcat, подождать, а затем reset рабочий на JK.

Анализ

Так как у меня есть 2 разъема на каждом Tomcat (AJP и HTTP), я все равно могу подключиться к приложению через HTTP. Приложение работает очень хорошо, как это, очень, очень быстро. Это совершенно нормально, поскольку я единственный, кто использует этот сервер (поскольку JK прекратил делегировать запросы этому Tomcat).

Чтобы лучше понять проблему, я взял дамп потока из Tomcat, который больше не отвечает, и из другого, который был перезапущен недавно (скажем, за 1 час до).

Экземпляр, который обычно отвечает на JK, показывает большинство потоков TP-ProcessorXXX в состоянии "Runnable" со следующей трассировкой стека:

java.net.SocketInputStream.socketRead0 ( native code )
java.net.SocketInputStream.read ( SocketInputStream.java:129 )
java.io.BufferedInputStream.fill ( BufferedInputStream.java:218 )
java.io.BufferedInputStream.read1 ( BufferedInputStream.java:258 )
java.io.BufferedInputStream.read ( BufferedInputStream.java:317 )
org.apache.jk.common.ChannelSocket.read ( ChannelSocket.java:621 )
org.apache.jk.common.ChannelSocket.receive ( ChannelSocket.java:559 )
org.apache.jk.common.ChannelSocket.processConnection ( ChannelSocket.java:686 )
org.apache.jk.common.ChannelSocket$SocketConnection.runIt ( ChannelSocket.java:891 )
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run ( ThreadPool.java:690 )
java.lang.Thread.run ( Thread.java:619 )

Придерживающийся экземпляр показывает большинство (все?) потоков TP-ProcessorXXX в состоянии "Ожидание". Они имеют следующую трассировку стека:

java.lang.Object.wait ( native code )
java.lang.Object.wait ( Object.java:485 )
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run ( ThreadPool.java:662 )
java.lang.Thread.run ( Thread.java:619 ) 

Я не знаю внутренних компонентов Tomcat, но я бы сделал вывод, что потоки "Ожидание" - это просто потоки, сидящие на пуле потоков. Итак, если они являются потоками, ожидающими внутри пула потоков, почему Tomcat не поставил их на обработку запросов обработки из JK?

РЕДАКТИРОВАТЬ: Я не знаю, нормально ли это, но Lambda Probe показывает мне, что в разделе "Состояние" есть много потоков в состоянии KeepAlive. Это как-то связано с проблемой, которую я испытываю?

Решение?

Итак, как я уже говорил ранее, единственным исправлением, которое я нашел, является остановка экземпляра Tomcat, остановка рабочего JK, ожидание последнего занятого подсчета, медленное падение, запуск Tomcat и включение рабочего стола JK один раз еще раз.

Что вызывает эту проблему? Как я должен его расследовать? Что я могу сделать для его решения?

Спасибо заранее.

Ответ 1

У вас настроены настройки памяти JVM и сборка мусора? Вы сделали бы это, когда вы установили свой CATALINA_OPTS

примеры:

CATALINA_OPTS="$CATALINA_OPTS -server -Xnoclassgc -Djava.awt.headless=true"
CATALINA_OPTS="$CATALINA_OPTS -Xms1024M -Xmx5120M -XX:MaxPermSize=256m"
CATALINA_OPTS="$CATALINA_OPTS -XX:-UseParallelGC"
CATALINA_OPTS="$CATALINA_OPTS -Xnoclassgc"

Существует множество философий, на которых лучше всего подходит настройка GC. Это зависит от того, какой код вы выполняете. Конфигурация выше работала лучше всего для среды с интенсивным использованием JSP (taglib вместо структуры MVC).

Ответ 2

Проверьте настройку времени ожидания. Кажется, вы получаете потоки в состояние keepalive, и они не теряют время. Похоже, ваш сервер не обнаруживает клиентские разъединения в течение разумного времени. Существует несколько переменных времени и количества.

Ответ 3

Сначала проверьте файл журнала.

Я думаю, файл журнала по умолчанию находится в /var/log/daemon.log. (этот файл не содержит только журналы из tomcat)

Ответ 4

У меня была аналогичная проблема с Weblogic. Причиной было то, что слишком много потоков ожидали сетевых ответов, а Weblogic не хватало памяти. Tomcat, вероятно, ведет себя одинаково. Вы можете попробовать:

  • Уменьшите время ожидания ваших соединений.
  • Уменьшить общее количество одновременных подключений, чтобы tomcat не запускал новые потоки при достижении этой суммы.
  • Легкое исправление, но не исправляет основную причину: возможно, что tomcat находится в состоянии нехватки памяти, хотя он пока не отображается в журналах. Увеличьте память tomcat, как описано выше.