Apache Tomcat задыхается после 300 подключений

16

У нас есть веб-сервер apache перед Tomcat, размещенный на EC2, тип экземпляра очень большой с 34 ГБ памяти.

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

В часы пик сервер блокирует около 300 процессов httpd. ps -ef | grep httpd | wc -l = 300

Я гуглил и нашел множество предложений, но, похоже, ничего не работает .. Ниже приведены некоторые настройки, которые я сделал, которые взяты непосредственно из онлайн-ресурсов.

Я увеличил пределы максимального соединения и максимальных клиентов как в Apache, так и в Tomcat. вот детали конфигурации:

// апач

   <IfModule prefork.c>
    StartServers 100
    MinSpareServers 10
    MaxSpareServers 10
    ServerLimit 50000
    MaxClients 50000
    MaxRequestsPerChild 2000
    </IfModule>

//Кот

    <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           connectionTimeout="600000"
           redirectPort="8443"
           enableLookups="false" maxThreads="1500"
           compressableMimeType="text/html,text/xml,text/plain,text/css,application/x-javascript,text/vnd.wap.wml,text/vnd.wap.wmlscript,application/xhtml+xml,application/xml-dtd,application/xslt+xml"
           compression="on"/>

//Sysctl.conf

 net.ipv4.tcp_tw_reuse=1
 net.ipv4.tcp_tw_recycle=1
 fs.file-max = 5049800
 vm.min_free_kbytes = 204800
 vm.page-cluster = 20
 vm.swappiness = 90
 net.ipv4.tcp_rfc1337=1
 net.ipv4.tcp_max_orphans = 65536
 net.ipv4.ip_local_port_range = 5000 65000
 net.core.somaxconn = 1024

Я пробовал многочисленные предложения, но тщетно .. как это исправить? Я уверен, что сервер m2xlarge должен обслуживать больше запросов, чем 300, возможно, у меня неправильная конфигурация.

Сервер блокируется только в часы пик и при наличии 300 одновременных запросов, ожидающих ответа от [300 секундной задержки] веб-службы.

Я просто следил за TCP-соединениями с помощью netstat

я нашел около 1000 соединений в состоянии TIME_WAIT, понятия не имею, что это будет означать с точки зрения производительности, я уверен, что это должно добавить к проблеме.

Выход ТОП

 8902  root      25   0 19.6g 3.0g  12m S  3.3  8.8  13:35.77 java
 24907 membase   25   0  753m 634m 2528 S  2.7  1.8 285:18.88 beam.smp
 24999 membase   15   0  266m 121m 3160 S  0.7  0.3  51:30.37 memcached
 27578 apache    15   0  230m 6300 1536 S  0.7  0.0   0:00.03 httpd
 28551 root      15   0 11124 1492  892 R  0.3  0.0   0:00.25 top


 Output of free -m
 total       used       free     shared    buffers    cached
 35007       8470       26536    0          1         61
 8407        26599
 15999       15         15984

 output of iostat
 avg-cpu:  %user   %nice %system %iowait  %steal   %idle
      26.21    0.00    0.48    0.13    0.02   73.15

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda1             14.36         4.77       329.37    9005402  622367592
sdb               0.00         0.00         0.00       1210         48

Также в пиковое время существует около 10-15 тыс. TCP-соединений с мембранным сервером [локальный]

НЕКОТОРЫЕ ОШИБКИ В MODJK LOG, я надеюсь, что это проливает некоторый свет на проблему ..

[Wed Jul 11 14:39:10.853 2012] [8365:46912560456400] [error]         ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:18.627 2012] [8322:46912560456400] [error] ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:21.358 2012] [8351:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)
[Wed Jul 11 14:39:22.640 2012] [8348:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)

~

Worker.properties
workers.tomcat_home=/usr/local/tomcat/
worker.list=loadbalancer
worker.tom1.port=8009
worker.tom1.host=localhost
worker.tom1.type=ajp13
worker.tom1.socket_keepalive=True
worker.tom1.connection_pool_timeout=600
worker.tom2.port=8109
worker.tom2.host=localhost
worker.tom2.type=ajp13
worker.tom2.socket_keepalive=True
worker.tom2.connection_pool_timeout=600
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tom1,tom2
worker.loadbalancer.sticky_session=True
worker.tom1.lbfactor=1
worker.tom1.socket_timeout=600
worker.tom2.lbfactor=1
worker.tom2.socket_timeout=600

// решаемые

Спасибо всем за ваши ценные предложения. Я пропустил настройки maxThreads для разъема AJP 1.3. Теперь все кажется под контролем.

Я также начал бы смотреть на серверы, основанные даже на nginx.

Джон Титус
источник
Каковы ваши настройки Keepalive?
Том О'Коннор
Какую ошибку получают клиенты при попытке загрузить страницу?
Шейн Мэдден
1
Вы увеличили максимально допустимое количество открытых описаний файлов для пользователя apache / httpd?
Голя
@ Tom My Keep Alive Настройки - KeepAliveTimeout 10 в httpd.conf
Джон Титус
3
Как выглядит результат topв эти времена? Как насчет free -m? И наконец iostat?
Zypher

Ответы:

13

Вы увеличили maxThreads в коннекторе AJP 1.3 на порту 8009?

HTTP500
источник
1500 - это то, что у меня есть в каждом экземпляре кота
Джон Титус
@john, вы говорите, что для каждого соединителя вы указали maxThreads = "1500"? Можете ли вы опубликовать свой раздел для AJP 1.3 Connector (порт 8009)?
HTTP500
спасибо за указание на это .. нет настройки maxThreads для AJP1.3 вообще .. может ли это быть причиной?
Джон Титус
1
Да, добавьте maxThreads в раздел для этого соединителя. По умолчанию используется значение 200.
HTTP500
6

Подумайте о настройке асинхронного прокси-сервера, такого как nginxили lighttpdперед Apache. Apache обслуживает контент синхронно, поэтому работники блокируются, пока клиенты не загрузят сгенерированный контент полностью (подробнее здесь ). Настройка асинхронного (неблокирующего) прокси-сервера обычно значительно улучшает ситуацию (я использовал для уменьшения числа одновременно работающих рабочих Apache с 30 до 3-5, используя его nginxв качестве внешнего прокси-сервера).

Alex
источник
5

Я подозреваю, что ваша проблема в Tomcat, а не Apache, из журналов, которые вы показали в любом случае. Когда вы получаете сообщение об ошибке «110» при попытке подключиться к tomcat, это указывает на то, что у вас есть очередь подключений, ожидающих обработки, которые больше не могут вписаться в настройку невыполненного прослушивания для сокета прослушивания в tomcat.

From the listen manpage:
   The  backlog  parameter defines the maximum length the queue of pending 
   connections may grow to.  If a connection request arrives with
   the queue full the client may receive an error with an indication
   of ECONNREFUSED or, if the underlying protocol supports  
   retransmission, the request may be ignored so that retries succeed.

Если бы мне пришлось угадывать, я бы заподозрил, что подавляющее большинство HTTP-запросов, когда сервер «задыхается», блокируется, ожидая, что что-то вернется из tomcat. Могу поспорить, что если вы попытаетесь получить статический контент, напрямую обслуживаемый apache (вместо того, чтобы быть прокси-сервером tomcat), это сработает, даже если его обычно «задыхается».

К сожалению, я не знаком с tomcat, но есть ли способ манипулировать настройками параллелизма?

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

В одном из ваших комментариев вы упомянули, что данные устаревают через 2 минуты. Я бы посоветовал кэшировать ответ, полученный от этой службы, на две минуты, чтобы уменьшить количество одновременных подключений, которые вы подключаете к внешней веб-службе.

Мэтью Ифе
источник
2

Первым шагом для устранения этой проблемы является включение mod_status в Apache и изучение его отчета - пока вы этого не сделаете, на самом деле вы идете вслепую. Это не праведно. ;-)

Второе, что нужно упомянуть (мне самим не нравятся ответы на вопросы, которые я не задавал, но ...), это использование более эффективных и специальных интерфейсных серверов, таких как nginx.

Кроме того , ты точно restartапач, или просто gracefulLY перезарядил его? :)

poige
источник
Апач перезапустился .. не изящная перезагрузка
Джон Титус
@johntitus, ну mod_status, в любом случае , это твой друг. :)
Пой
1

Для любого вида корпоративного развертывания prefork MPM является едва ли не самым худшим выбором, который вы можете сделать: он поглощает ресурсы, как никто другой, а перезапуск потоков занимает ВСЕГДА по сравнению с другими MPM.

По крайней мере, переключитесь на рабочий MPM (apache 2.2 и выше) или, что еще лучше, обновите до текущей стабильной версии 2.4.2 со стандартным событием MPM.

Оба из них легко справятся с тысячами одновременных соединений с минимальными издержками.

adaptr
источник
спасибо .. попробовал это тоже .. не повезло. TIME_WAIT соединения продолжают расти. Сервер перестает отвечать на 350 подключений
Джон Тит
1
Я не согласен с тем, что это худший выбор - это плохой выбор для этого контекста, и вполне вероятно, что проблемы будут облегчены с помощью многопоточного сервера, но лучшим решением будет использование сервера на основе событий (nginx или lighttpd). Apache, основанный на событиях, еще недостаточно развит, чтобы его можно было рассмотреть из корпоративного развертывания IMHO.
symcbean
1

Я знаю, что это старая история, но у меня есть 2 замечания.

Существует жёстко предел для ServerLimit Директивы. http://httpd.apache.org/docs/2.2/mod/mpm_common.html#serverlimit вы увидите, что это максимум 20000 / 200K.

Существует жесткое ограничение ServerLimit 20000, скомпилированное в сервер (для prefork MPM 200000). Это предназначено, чтобы избежать неприятных эффектов, вызванных опечатками.

2-ой Очевидно, nodybo упомянул, что установка этих 2 на один - очень плохая идея :

net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1

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

Я нашел очень хорошую статью, объясняющую это, но - это французский ;-) http://vincent.bernat.im/fr/blog/2014-tcp-time-wait-state-linux.html

надир
источник
0

очень большой с 34 ГБ памяти.

Большое железо не способ масштабировать веб-серверы, вы просто перемещаете узкие места вокруг. Но даже при таком большом количестве памяти я подозреваю, что 50000 подключений продвигают то, на что способна система, особенно если:

В часы пик сервер заглушает около 300 процессов httpd

Было бы полезно, если бы вы объяснили, что вы подразумеваете под «дросселями сервера».

Также очень странно иметь такой высокий предел для соединений, но очень низкий предел для гистерезиса (мин / макс запасных серверов).

Хотя приведенный вами фрагмент ошибок не показывает контрольного числа «слишком много открытых файлов», я бы начал с просмотра количества дескрипторов открытых файлов и настроек ulimit.

symcbean
источник
Серверные чоки, так как он не отвечает даже на обычные HTML-файлы ..
Джон Титус
Я изменил maxClients на 3000 сейчас .. все та же проблема
Джон Титус
0

Возможно, у пользователя Apache не хватает разрешенных файловых дескрипторов? Вы вообще не упомянули их в своем посте. Сколько файловых дескрипторов в настоящее время может иметь Apache?

Янне Пиккарайнен
источник
128192 файловых дескрипторов
Джон Титус
0

Это больше похоже на комментарий, но не могу, так как у меня меньше репутации. Наткнулся на точно такую ​​же проблему, как @john titus.

MaxThreadsДля решения проблемы мы установили AJP-коннектор близко к пределу нитей Apache.

Для мониторинга этого мы искали SYN_SENT справку о состоянии порта netstat с помощью команды netstat на нашем порту AJP.

netstat -an | grep :8102 | grep SYN_SENT | wc -l

Это снизилось до 0, что всегда было большим числом до ограничения MaxThread, установленного в AJP Connector.

Вайнит
источник