Apache+Tomcat имеет проблемы с соединением. Непонятные сообщения об ошибках. Отключение веб-сайтов, размещенных на Tomcat

Apache+Tomcat имеет проблемы с соединением. Непонятные сообщения об ошибках. Отключение веб-сайтов, размещенных на Tomcat

Настраивать:
Fedora 8
Apache 2.2.8
Tomcat 5.5.8
Apache пересылает запросы с помощью AJP.

Проблема:
Через определенный промежуток времени (не постоянный, может быть от часа до двух, от одного до нескольких дней) Tomcat падает. Он либо перестает отвечать, либо выдает общее сообщение «Сервис временно недоступен».

Диагноз:
Есть два сервера с одинаковой настройкой. На одном из них находится сайт с большим трафиком (несколько запросов в секунду), на другом — с низким трафиком (несколько запросов каждые несколько минут). Оба сайта имеют совершенно разные кодовые базы, но у них наблюдаются схожие проблемы.

На первом сервере, когда возникает проблема, все потоки медленно начинают загружаться, пока не будет достигнут предел (MaxThreads 200). В этот момент сервер больше не отвечает (и выдает страницу о недоступности сервиса через длительный промежуток времени).

На втором сервере при возникновении проблемы запросы выполняются долго, а после их завершения вы видите только страницу о недоступности сервиса.

За исключением упоминания проблемы MaxThreads, в журналах Tomcat не указано никаких конкретных проблем, которые могли бы быть причиной этого.

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

[error] (70007)The timeout specified has expired: ajp_ilink_receive() can't receive header
[error] (104)Connection reset by peer: ajp_ilink_receive() can't receive header
[error] proxy: AJP: disabled connection for (localhost)
[error] ajp_read_header: ajp_ilink_receive failed
[error] (120006)APR does not understand this error code: proxy: read response failed from 127.0.0.1:8009 (localhost)
[error] ap_proxy_connect_backend disabling worker for (localhost)

Другая странность, которую мы заметили на сервере с большим трафиком, заключается в том, что прямо перед тем, как проблема начинает проявляться, запросы к базе данных занимают гораздо больше времени, чем раньше (2000-5000 мс по сравнению с обычными 5-50 мс). Это длится всего 2-4 секунды, прежде чем появляется сообщение MaxThreads. Я предполагаю, что это результат того, что сервер внезапно сталкивается со слишком большим количеством данных/трафика/потоков.

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

Разрешение:
Очевидным решением было бы вернуться к настройке двух сетевых карт. Проблема в том, что это вызовет некоторые осложнения с настройкой сети, и это похоже на игнорирование проблемы. Мы бы предпочли попробовать запустить его на настройке одной сетевой карты.

Поиск в Google различных сообщений об ошибках не дал ничего полезного (либо старые решения, либо не имеющие отношения к нашей проблеме).

Мы пробовали настраивать различные тайм-ауты, но из-за этого сервер работал немного дольше, прежде чем завис.

Мы не уверены, куда смотреть, чтобы диагностировать проблему дальше. Мы все еще хватаемся за соломинку, пытаясь понять, в чем может быть проблема:

1) Настройка AJP и Tomcat неверна или устарела (т. е. есть известные ошибки?)
2) Настройка сети (две сетевые карты против одной) вызывает путаницу или проблемы с пропускной способностью.
3) Сами веб-сайты (нет общего кода, не используются платформы, только базовый код Java с сервлетами и JSP)

Обновление 1:
Следуя полезному совету Дэвида Пэшли, я сделал трассировку стека/дамп потока во время проблемы. Я обнаружил, что все 200 потоков находились в одном из следующих состояний:

"TP-Processor200" daemon prio=1 tid=0x73a4dbf0 nid=0x70dd waiting for monitor entry [0x6d3ef000..0x6d3efeb0]
at  oracle.jdbc.pool.OracleConnectionCacheImpl.getActiveSize(OracleConnectionCacheImpl.java:988)
- waiting to lock <0x7e3455a0> (a oracle.jdbc.pool.OracleConnectionCacheImpl)
[further stack trace removed for brevity]

"TP-Processor3" daemon prio=1 tid=0x08f142a8 nid=0x652a waiting for monitor entry [0x75c7d000..0x75c7ddb0]
at oracle.jdbc.pool.OracleConnectionCacheImpl.getConnection(OracleConnectionCacheImpl.java:268)
- waiting to lock <0x7e3455a0> (a oracle.jdbc.pool.OracleConnectionCacheImpl)
[further stack trace removed for brevity]

Любопытно, что только один поток из всех 200 находился в таком состоянии:

"TP-Processor2" daemon prio=1 tid=0x08f135a8 nid=0x6529 runnable [0x75cfe000..0x75cfef30]
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at oracle.net.ns.Packet.receive(Unknown Source)
at oracle.net.ns.DataPacket.receive(Unknown Source)
at oracle.net.ns.NetInputStream.getNextPacket(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
[further stack trace removed for brevity]

Возможно, драйвер Oracle в этом потоке заставляет все остальные потоки ждать его завершения. По какой-то причине он должен застрять в этом состоянии чтения (сервер никогда не восстанавливается самостоятельно, требуется перезапуск).

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

решение1

Оказывается, эта версия (classes12 — довольно старая) драйвера Oracle содержала различные ошибки, которые вызывали взаимоблокировку (как видно из состояния TP-Processor2, приведенного выше). Она не активировалась, пока мы не переключились на новую среду. Обновление до последней версии (ojdbc14) решило проблему на основном сервере.

решение2

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

  • Получите трассировку стека, используя jstack или kill -3 $process_id. Посмотрите, что делают ваши потоки, когда он умирает. Если они все ждут в базе данных, это хороший указатель на мою теорию. Они все могут ждать какой-то блокировки.
  • Установите LambdaProbe. Это бесценно для выяснения того, что делает ваш tomcat.
  • Обновите свой tomcat. 5.5.8 невероятно старая. Думаю, сейчас они на 5.5.27.

решение3

Добавьте connectionTimeout и keepAliveTimeout в ваш коннектор AJP, который находится в /etc/tomcat7/server.xml.

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" 
           connectionTimeout="10000" keepAliveTimeout="10000" />

Информация о соединителе AJP наhttps://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html

  • connectionTimeout = Количество миллисекунд, в течение которых этот коннектор будет ждать, после принятия соединения, пока не будет представлена ​​строка URI запроса. Значение по умолчанию для коннекторов протокола AJP равно -1 (т.е. бесконечно).

  • keepAliveTimeout = Количество миллисекунд, в течение которых этот коннектор будет ожидать другого запроса AJP перед закрытием соединения. Значением по умолчанию является использование значения, установленного для атрибута connectionTimeout.

Если значения connectionTimeout и keepAliveTimeout не определены, то соединения AJP будут поддерживаться в активном состоянии бесконечно. Это приводит к появлению большого количества потоков, максимальное количество потоков по умолчанию — 200.

Я рекомендую установить psi-probe — продвинутый менеджер и монитор для Apache Tomcat, созданный на основе Lambda Probe.https://code.google.com/p/psi-probe/

решение4

У меня были лучшие результаты с mod_proxy вместо mod_ajp в плане стабильности, так что попробуйте это решение. Оно неинвазивное — в лучшем случае решит проблему, а в худшем исключит mod_ajp.

Кроме этого, похоже, что ваши Tomcats перестали отвечать, и все потоки запросов завязаны. Пусть ваша команда разработчиков посмотрит, что происходит -беру дамп потокаи донести это до них будет полезно.

Связанный контент