AJP закончился поток

У меня есть два прокси-сервера балансировки нагрузки apache (с именами A1, A2), работающие с mod_jk, и два веб-сервера Jboss (с именами J1, J2).

Версия Jboss — jboss-eap-5.1. Версия Apache 2.2.15. ОС: Red Hat Enterprise Linux Server версии 6.4 (Сантьяго). И A1, и A2 могут перенаправить запрос (с портом 80) извне на J1, J2 (оба порта 8080). Настройки A1, A2 одинаковы (кроме HostIP). J1, J2 также имеют одинаковые настройки (кроме HostIP и jvmRoute).

У меня есть некоторые проблемы с этой архитектурой. J1 и J2 могут хорошо обработать запрос A1 (получить запрос -> создать поток для обработки -> завершить процесс -> закрыть поток).

Но запрос А2 странный. Когда процесс завершился, поток не закрылся. И сетевое подключение останется в состоянии ESTABLISHED. Я использовал jstack PID для проверки, и есть много следующих утверждений:

"ajp-XX.XX.72.12-8009-240" daemon prio=10 tid=0x00007f791418e800 nid=0x7793 runnable [0x00007f7875d5c000]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:129)
    at org.apache.coyote.ajp.AjpProcessor.read(AjpProcessor.java:1036)
    at org.apache.coyote.ajp.AjpProcessor.readMessage(AjpProcessor.java:1115)
    at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:383)
    at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:385)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:451)
    at java.lang.Thread.run(Thread.java:662)`

Сравнил приведенный выше PID (nid=0x7793) с ps -efT | grep 30611 можно получить следующее: `xxxx 17869 30611 17821 0 20:40 ? 00:00:00 /usr/local/java/bin/java -program.name=run.sh ...

И хотя я использую netstat -A inet, таких подключений много:

Proto Recv-Q Send-Q Local Address               Foreign Address             State      
tcp        0      0 npouiap2:8009               10.100.84.34:49666          ESTABLISHED 
tcp        0      0 npouiap2:8009               10.100.84.34:50374          ESTABLISHED 
tcp        0      0 npouiap2:8009               10.100.84.34:50507          ESTABLISHED 

person nsnosheep    schedule 27.10.2014    source источник


Ответы (1)


Проблема может заключаться в том, что потоки не бездействуют, так как соединения AJP по умолчанию являются постоянными.

Вы можете попробовать один из этих вариантов:

  1. Увеличьте maxThreads на JBoss, чтобы он совпадал с "max threads" (точные директивы различаются в зависимости от MPM) на httpd
  2. Включите mod_jk's отключить параметр повторного использования

Вариант 2 проще всего применить и проверить, сохраняется ли проблема.

person Federico Sierra    schedule 28.10.2014
comment
Привет Сьерра, спасибо за ваш ответ. Проблема в том, что A1, A2 имеют одинаковые настройки, но только соединение с A2 приведет к зависанию потока AJP. Я думал, что это не может быть вызвано настройкой maxThreads. И вариант 2, кажется, решает проблему зависания соединения на A1, A2. Но ситуация такова, что соединения висят на J1,J2. - person nsnosheep; 28.10.2014
comment
@nsnosheep Вы пытались остановить сервер A1 и обрабатывать запросы только с A2? Есть ли какое-либо сообщение в журнале ошибок apache? - person Federico Sierra; 28.10.2014
comment
@Sierra, я не могу остановить сервер A1. Потому что он работает в производственной среде моей компании и предоставляет услуги 7*24. Я запускал tcpdump на J1 и J2. Выясните, что если запрос будет отправлен с A1, J1 и J2 получат пакеты одновременно (один получит 11 пакетов, а другой — 3 пакета). Если запрос отправляется из A2, только один из J1 или J2 получит пакеты (14 пакетов). Смотрю те пакеты, обнаружил, что в пакетах от А2 есть 3 SYN пакета, которые не отправились от А1. - person nsnosheep; 28.10.2014
comment
@nsnosheep AJP — постоянный протокол. Однажды установленные соединения никогда не освобождаются, а используются повторно. Хорошо, если вы не установите connectionTimeout, который в основном не является тайм-аутом соединения, а скорее тайм-аутом между двумя HTTP-запросами, сделанными через постоянное соединение. Для этого, я думаю, A1 в какой-то момент занял все потоки от JBoss. Вы можете попробовать добавить опцию отключения повторного использования и проверить, если я ошибаюсь. - person Federico Sierra; 28.10.2014
comment
Привет, Сьерра. Я думал об этом. Завтра я обсужу это с моими коллегами, отвечающими за Infra. Но есть что-то странное. Если A1 занял все потоки JBoss, почему я все еще могу отправить запрос от A2 и получить содержимое? Спасибо за Ваш ответ. :D - person nsnosheep; 28.10.2014
comment
Привет, в этом случае может быть заполнен только один J1 или J2 (или оба), и результат зависит от сервера. Доказать, что это иногда непростая задача, и может занять много времени, особенно в производственных средах. - person Federico Sierra; 28.10.2014
comment
Привет, @Federico Sierra, я решил это. Потоки J1/J2 зависают, потому что A1 или A2 неактивны, и соединение автоматически прерывается (время ожидания соединения истекло в worker.properties). Но J1/J2 не устанавливает тайм-аут. Таким образом, этот поток J1/J2 думает, что соединение все еще установлено и больше не может получать трафик. Пока поступает новый трафик, A1 или A2 создадут новое соединение (старое разорвется по истечении времени ожидания соединения). Затем мы увидим, что J1/J2 создают новые потоки для обработки этих новых соединений. - person nsnosheep; 08.12.2014
comment
Таким образом, мы должны установить один и тот же срок ожидания соединения на Apache и Jboss при использовании пула соединений, тогда потоки больше не будут зависать. Спасибо за помощь, с уважением. - person nsnosheep; 08.12.2014