Установка:
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 в этом потоке заставляет все остальные потоки ждать его завершения. По какой-то причине он должен застрять в этом состоянии чтения (сервер никогда не восстанавливается самостоятельно, он требует перезагрузки).
Это говорит о том, что оно должно быть связано либо с сетью между сервером и базой данных, либо с самой базой данных. Мы продолжаем диагностику, но любые советы будут полезны.
источник
Ответы:
Оказывается, что в этой версии (классы 12 - довольно старая) драйвера Oracle были различные ошибки, которые вызывали взаимоблокировку (как видно из приведенного выше состояния TP-Processor2). Он не стал активным, пока мы не переключились на новую среду. Обновление до последней версии (ojdbc14) решило проблему на основном сервере.
источник
Из описания я бы предположил, что проблема может быть связана с тем, что запросы к базе данных занимают слишком много времени. Если запросы занимают больше времени, запрос будет длиться дольше, и поэтому у вас будет больше запущенных одновременно. Как вы видите, у вас закончились потоки котов. Когда вы решите проблему с базой данных, все будет в порядке.
источник
Добавьте connectionTimeout и keepAliveTimeout к вашему коннектору AJP, расположенному в /etc/tomcat7/server.xml.
Информация о соединителе 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/
источник
Из-за того, как работает AJP, постоянные соединения между apache (использующие mod_proxy_ajp или mod_jk) могут быть безопасно закрыты только клиентом . В этом случае клиент - это рабочий apache, который открывается, а затем сохраняет соединение с tomcat на весь срок службы для рабочего процесса .
Из-за этого поведения у вас не может быть больше рабочих Apache, чем рабочих потоков Tomcat. Это приведет к тому, что дополнительные работники http не смогут подключиться к tomcat (поскольку очередь приема заполнена) и пометит ваш бэкэнд как DOWN!
источник
У меня были лучшие результаты с mod_proxy вместо mod_ajp с точки зрения стабильности, поэтому попробуйте это решение. Он неинвазивен - в лучшем случае он решит проблему, а в худшем исключит mod_ajp.
Кроме того, звучит так, как будто ваши Tomcats перестают отвечать, и все потоки запросов связаны. Пусть ваша команда разработчиков рассмотрит, что происходит - будет полезен дамп потока и его доставка.
источник
Первое, о чем я думаю, когда слышу, что сервер какое-то время работает, внезапно замедляется и начинает возникать сбой службы, это то, что у него заканчивается ОЗУ и происходит перестановка. Я не уверен в том, что сбои AJP, которые вы видите, могут быть следствием таймаутов, но это не кажется совершенно необоснованным; не вижу никакого очевидного способа, которым это соединится с NIC, все же. В любом случае, я рекомендую вам получить представление о том, что происходит с использованием вашей памяти, когда происходят эти события.
Если у вас заканчивается ОЗУ, вам может потребоваться отключить Apache
MaxClients
и увеличить егоListenBacklog
.Кстати, спасибо, что сделали ваш вопрос так хорошо организованным и полным.
источник
У меня были подобные ошибки журнала в среде Redhat с proxy_ajp и Tomcat. Решено обновлением пакета httpd:
от:
чтобы:
Затем перезапустил apache, после чего перезапустил Tomcat.
Это исправило это для меня!
источник