Установка:
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. Я предполагаю, что это результат того, что сервер внезапно столкнулся со слишком большим объемом данных / трафика / потоков.
Справочная информация:
Эти два сервера работали без проблем в течение достаточно долгого времени. Системы были фактически настроены каждая с использованием двух сетевых карт в течение этого времени. Они разделили внутренний и внешний трафик. После обновления сети мы переместили эти серверы на отдельные сетевые карты (это было рекомендовано нам по соображениям безопасности / простоты). После этого изменения серверы начали испытывать эти проблемы.
Решение
. Очевидным решением будет возврат к настройке двух сетевых карт. Проблемы с этим состоят в том, что это может вызвать некоторые сложности с настройкой сети, и кажется, что игнорирование проблемы. Мы бы предпочли попробовать и запустить его на одной установке NIC.
Поиск различных сообщений об ошибках не дал ничего полезного (старых решений или не относящихся к нашей проблеме).
Мы попытались настроить различные таймауты, но это только заставило сервер работать немного дольше, прежде чем умереть.
Мы не уверены, где искать, чтобы диагностировать проблему дальше. Мы все еще цепляемся за соломинку, в чем может быть проблема:
1) Настройка с AJP и Tomcat неверна или устарела (то есть известны ошибки?).
2) Настройка сети (две NIC против одной NIC) вызывает проблемы путаницы или пропускной способности.
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 в этом потоке заставляет все остальные потоки ждать его завершения. По какой-то причине он должен застрять в этом состоянии чтения (сервер никогда не восстанавливается самостоятельно, он требует перезагрузки).
Это говорит о том, что оно должно быть связано либо с сетью между сервером и базой данных, либо с самой базой данных. Мы продолжаем диагностику, но любые советы будут полезны.