Apache Tomcat задихається після 300 з'єднань


16

Перед Tomcat розміщено веб-сервер apache, розміщений на EC2, тип екземпляра надзвичайно великий із 34 Гб пам'яті.

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

У години пік сервер задихається приблизно в 300 процесах httpd. пс -еф | grep httpd | wc -l = 300

Я переглянув Google і знайшов численні пропозиції, але, здається, нічого не працює. Слідом за деякими конфігураціями, які я зробив, які безпосередньо взяті з інтернет-ресурсів.

Я збільшив ліміти максимального зв’язку та максимальних клієнтів як в апачі, так і в tomcat. ось деталі конфігурації:

// апач

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

// tomcat

    <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-15k tcp підключень до мембранного сервера [локальний]

ДЕЯКІ ПОМИЛКИ В ЛОГІ MODJK, я сподіваюся, що це кине світло на проблему ..

[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

// Вирішено

thansk все для ваших цінних пропозицій .. Я пропустив налаштування maxThreads для роз'єму AJP 1.3. Тепер все здається під контроль.

Я також почав би переглядати навіть такі сервери, як nginx.


Які ваші налаштування Keepalive?
Том О'Коннор

Яку помилку отримують клієнти назад при спробі завантажити сторінку?
Шейн Медден

1
Ви збільшили максимально дозволені відкриті описи файлів для користувача apache / httpd?
golja

Налаштування @Tom My Keep Alive - KeepAliveTimeout 10 у httpd.conf
Джон Титус

3
Як виглядає вихід topу цей час? Як щодо free -m? І останнє iostat?
Zypher

Відповіді:


13

Ви збільшили maxThreads у роз'ємі AJP 1.3 на порту 8009?


1500 - це те, що я маю на екземпляр tomcat
John Titus

@john, Ви кажете, що для кожного роз'єму ви вказали maxThreads = "1500"? Чи можете ви розмістити свою строфу для роз'єму AJP 1.3 (порт 8009)?
HTTP500

спасибі за вказівку на це .. немає налаштування maxThreads для AJP1.3 взагалі .. це може бути причиною?
John Titus

1
Так, додайте maxThreads до строфи цього роз'єму. За замовчуванням - 200.
HTTP500

6

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


5

Я підозрюю, що ваша проблема полягає в тому, що ви не показали 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. Б'юсь об заклад, якщо ви спробували отримати якийсь статичний вміст, який безпосередньо обслуговується апашем (замість того, щоб прокси до Tomcat), що це спрацює навіть у тому випадку, коли його звичайно «задихається».

На жаль, я не знайомий з tomcat, але чи є спосіб замість цього налаштувати параметри одночасності?

О, і вам може знадобитися також врахувати можливість того, що його зовнішні мережеві послуги обмежують кількість з'єднань, які він робить для вас , до 300, тому не має значення, скільки маніпулювання одночасністю ви робите на передній стороні якщо практично кожне з'єднання, яке ви здійснюєте, покладається на відповідь зовнішньої веб-служби.

В одному зі своїх коментарів згадані вами дані стають застарілими через 2 хвилини. Я б запропонував кешувати відповідь, яку ви отримуєте від цієї послуги протягом двох хвилин, щоб зменшити кількість одночасних з'єднань, які ви переходите на зовнішню веб-службу.


2

Першим кроком для усунення цього завдання є включення mod_status Apache та вивчення його звіту - поки ви цього не зробите, насправді ви сліпо ходите. Це не праведник. ;-)

Друге, що слід зазначити (я не люблю, щоб мені відповідали відповіді на запитання, які я не задавав, але ...) - це використання більш ефективних та спеціальних серверів, таких як фронтальні nginx.

Крім того , ти точно restartапач, або просто gracefulLY перезарядив його? :)


Apache перезапустив .. не витончене перезавантаження
John Titus

@johntitus, ну, mod_statusвсе-таки твій друг. :)
poige

1

Для будь-якого типу розгортання підприємств-y MPM prefork - це майже найгірший вибір, який ви можете зробити: він збиває ресурси, як ніхто, а перезапуск потоків займає FOREVER порівняно з іншими MPM.

По крайней мере, перейдіть на MPM- робочий (апаш 2.2 і вище) або - ще краще - оновіть до поточної стабільної версії 2.4.2 з MPM події за замовчуванням .

Обидва вони легко оброблять тисячі одночасних з'єднань з дуже невеликими накладними витратами.


дякую .. спробував це теж .. не пощастило. TIME_WAIT-з'єднання постійно збільшуються. Сервер перестає реагувати на 350 з'єднань
John Titus

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, зібраний на сервер (для префорка 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

Було б корисно, якби ви пояснили, що ви маєте на увазі під "заклинанням сервера".

Також дуже дивно мати такий високий ліміт підключень, але дуже низький межа для гістерезису (min / max запасні сервери).

Хоча введений вами витяг помилок не показує показову інформацію "надто багато відкритих файлів", я б почав з перегляду кількості відкритих дескрипторів файлів та нескінченних налаштувань.


Сервер вибирає, як в ньому не відповідає навіть нормальним HTML-файлам ..
Джон Титус

Я змінив maxClients на 3000 зараз .. все одно те саме питання
John Titus

0

Можливо, у користувача Apache не вистачає дозволених ручок файлів? Ви їх взагалі не згадували у своєму пості. Скільки файлів обробляє Apache на даний момент дозволено?


128192 файлових ручок
John Titus

0

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

Ми зробили роз'єм AJP MaxThreadsЩоб вирішити проблему, близько до межі Apache Thread.

Для моніторингу цього, ми шукали SYN_SENT довідку про стан порту netstat за допомогою команди netstat на нашому порту AJP.

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

Це знизилося до 0, що завжди було великим числом до встановленого на AJP Connector обмеження MaxThread.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.