Продуктивність Apache різко знижується вище ~ 256 одночасних запитів


14

Я розміщую відносно низький трафік сайту, який відчуває великий сплеск відвідувачів раз на тиждень після оновлення сайту. Під час цього сплеску продуктивність сайту надзвичайно погана порівняно з рештою тижня. Фактично навантаження на сервери залишається дуже низькою, надійно під 10% процесора та менше 30% оперативної пам’яті (обладнання повинно бути повним надмірним для того, що ми насправді робимо), але чомусь Apache, здається, не в змозі впоратися з кількістю запитів. Ми запускаємо apache 2.2.3 на RHEL 5.7, ядро ​​2.6.18-274.7.1.el5, x86_64.

Намагаючись відтворити таку поведінку в неробочий час з ab, я знаходжу значне зниження продуктивності при перевищенні приблизно 256 користувачів. Запуск тесту з найменшим можливим випадком використання, який я міг би придумати (витягнутий статичний текстовий файл, загальна кількість 223 байт), стабільно нормальний при 245 одночасних запитах:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       15   25   5.8     24      37
Processing:    15   65  22.9     76      96
Waiting:       15   64  23.0     76      96
Total:         30   90  27.4    100     125

Percentage of the requests served within a certain time (ms)
  50%    100
  66%    108
  75%    111
  80%    113
  90%    118
  95%    120
  98%    122
  99%    123
 100%    125 (longest request)

Але як тільки я заграю до 265 одночасних запитів, підгрупа їх починає забирати безглузді кількості часу:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       13  195 692.6     26    3028
Processing:    15   65  21.3     72     100
Waiting:       15   65  21.3     71      99
Total:         32  260 681.7    101    3058

Percentage of the requests served within a certain time (ms)
  50%    101
  66%    108
  75%    112
  80%    116
  90%    121
  95%   3028
  98%   3040
  99%   3044
 100%   3058 (longest request)

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

Природно, я припускав, що це спричинено обмеженням потоку в префорках, тому я пішов вперед і відкоригував конфігурацію, щоб подвоїти кількість доступних ниток і не допустити, щоб пул ниток не рос і скорочувався без необхідності:

<IfModule prefork.c>
StartServers     512
MinSpareServers  512
MaxSpareServers  512
ServerLimit      512
MaxClients       512
MaxRequestsPerChild  5000
</IfModule>

mod_status підтверджує, що я зараз працюю з 512 доступними потоками

8 requests currently being processed, 504 idle workers

Однак спроби 265 одночасних запитів все ще дають майже однакові результати, ніж раніше

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       25  211 714.7     31    3034
Processing:    17   94  28.6    103     138
Waiting:       17   93  28.5    103     138
Total:         57  306 700.8    138    3071

Percentage of the requests served within a certain time (ms)
  50%    138
  66%    145
  75%    150
  80%    161
  90%    167
  95%   3066
  98%   3068
  99%   3068
 100%   3071 (longest request)

Після перегляду документації (та обміну стеками) я втрачаю подальші настройки конфігурації, щоб спробувати усунути це вузьке місце. Чи є щось, чого мені не вистачає? Чи варто починати шукати відповіді поза апаш? Хтось ще бачив таку поведінку? Будь-яка допомога буде дуже вдячна.

Редагувати:

Відповідно до порад Лададада, я біг напружено проти апаша. Я спробував з -tt і -T кілька разів, і нічого звичайного не вдалося знайти. Потім я спробував запустити strace -c проти всіх поточно запущених процесів apache, і отримав це:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 22.09    0.317836           5     62128      4833 open
 19.91    0.286388           4     65374      1896 lstat
 13.06    0.187854           0    407433           pread
 10.70    0.153862           6     27076           semop
  7.88    0.113343           3     38598           poll
  6.86    0.098694           1    100954     14380 read

(... скорочено)

Якщо я читаю це право (і маю на собі, оскільки я дуже часто не використовую напругу), жоден із системних дзвінків не може враховувати кількість часу, який займають ці запити. Це майже схоже на те, що вузьке місце виникає до того, як запити навіть потраплять у робочі нитки.

EDIT 2:

Як запропонували кілька людей, я знову запустив тест на самому веб-сервері (раніше тест виконувався з нейтрального веб-сайту). Результати були дивовижними:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   11   6.6     12      21
Processing:     5  247 971.0     10    4204
Waiting:        3  245 971.3      7    4204
Total:         16  259 973.3     21    4225

Percentage of the requests served within a certain time (ms)
  50%     21
  66%     23
  75%     24
  80%     24
  90%     26
  95%   4225
  98%   4225
  99%   4225
 100%   4225 (longest request)

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

Знову запустивши тест з іншої машини в тій же локальній мережі, що і хост Apache, я бачу набагато більш розумні результати:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1    2   0.8      2       4
Processing:    13  118  99.8    205     222
Waiting:       13  118  99.7    204     222
Total:         15  121  99.7    207     225

Percentage of the requests served within a certain time (ms)
  50%    207
  66%    219
  75%    220
  80%    221
  90%    222
  95%    224
  98%    224
  99%    225
 100%    225 (longest request)

Ці два тести разом викликають цілу низку питань, але окремо від цього зараз є вагомий випадок для якогось серйозного вузького вузького місця, яке відбувається під певним навантаженням. Я думаю, що наступними кроками буде вивчення мережевого рівня окремо.


Варіанти, які слід врахувати: CloudFlare, drupal.org/project/boost , CDN, кеш лаку.
ceejayoz

Ви нічого не говорите нам про те, що робить цей сервер (у реальному світі), окрім обслуговування HTTP-запитів. Чи задіяна база даних (чи якийсь інший загальний ресурс, який може страждати від заблокування)? Якщо проблема трапляється раптово при ТОЧНО 256 запитах (ОК у 255), ймовірно, перекидається якийсь зовнішній ресурс. (Ваш стрибок, що обслуговує статичну сторінку, безумовно, також ненормальний - див. Відповідь Лададада на деякі поради щодо налагодження там)
voretaq7

ceejayoz: Я ціную пропозиції, але принципово вважаю, що Apache не повинен бути таким повільним. Ми можемо зробити багато речей, щоб пом'якшити дію проблеми, але я хотів би скоріше виправити або принаймні зрозуміти це.
cmckendry

voretaq7: Я спочатку міркував за цими ж принципами, оскільки типовий запит також передбачав би php / mysql, але проблема зберігається на тому самому порозі навіть при поданні повністю статичного вмісту.
cmckendry

1
Це справжній сервер чи VM? Ви робите тест з localhost, локальної мережі чи Інтернету? Мінімальний час відгуку в діапазоні 100 мс підказує тести з Інтернету. Спробуйте протестувати у localhost - можливо, ваш постачальник просто замовчує вас.
Томецький

Відповіді:


4

Те, що я зробив би в цій ситуації, - це керування

strace -f -p <PID> -tt -T -s 500 -o trace.txt

на одному з ваших процесів Apache під час тесту ab, поки ви не зафіксуєте одну з повільних реакцій. Тоді подивіться наскрізь trace.txt.

Параметри -ttта -Tпараметри дають часові позначки початку та тривалості кожного системного дзвінка, щоб допомогти визначити повільні.

Ви можете знайти один повільний системний виклик, наприклад, open()або stat()ви можете знайти швидкий дзвінок із (можливо, декількома) poll()дзвінками безпосередньо після нього. Якщо ви знайдете той, який працює у файлі чи мережевому з'єднанні (цілком ймовірно), огляньтесь назад через слід, поки не знайдете цей файл або ручку з'єднання. Попередні дзвінки на цю ж ручку повинні дати вам уявлення про те, що poll()чекало.


Гарна ідея, дивлячись на -cваріант. Чи гарантували ви, що дитина Apache, яку ви шукали, подав хоча б один із повільних запитів за цей час? (Я навіть не впевнений, як би ви це зробили, крім straceодночасного запуску на всіх дітей.)

На жаль, straceне дає нам повної картини того, що працює запущена програма. Він відстежує лише системні дзвінки. У програмі може статися багато, що не вимагає ядра нічого не вимагати. Щоб зрозуміти, чи відбувається це, ви можете подивитися часові позначки початку кожного виклику системи. Якщо ви бачите значні прогалини, саме тут йде час. Це не легко зрозуміти, і в будь-якому випадку завжди є невеликі зазори між системними дзвінками.

Оскільки ви сказали, що використання процесора залишається низьким, це, мабуть, не надто багато, що відбувається між системними дзвінками, але це варто перевірити.


Більш уважно придивившись до результатів ab:

Раптовий стрибок часів реакції (схоже, немає часу реакції десь між 150 мс і 3000 мс) говорить про те, що десь відбувається певний час очікування, який спрацьовує вище приблизно 256 одночасних з'єднань. Більш плавна деградація очікується, якщо у вас закінчується цикл оперативної пам'яті або процесора, нормальний IO.

По-друге, повільна abреакція показує, що 3000 мс були витрачені у connectфазі. Майже всі вони займали близько 30 мс, але 5% займали 3000 мс. Це говорить про те, що проблема полягає в мережі.

Звідки ти біжиш ab? Чи можете ви спробувати його з тієї ж мережі, що і машина Apache?

Щоб отримати додаткові дані, спробуйте запустити tcpdumpна обох кінцях з'єднання (бажано з ntpзапуском на обох кінцях, щоб ви могли синхронізувати два захоплення вгору.) Та шукайте будь-які повторні передачі tcp. Wireshark особливо хороший для аналізу відвалів, оскільки він виділяє ретрансляцію tcp іншим кольором, що робить їх легко знайти.

Можливо, варто також переглянути журнали будь-яких мережевих пристроїв, до яких ви маєте доступ. Нещодавно я зіткнувся з проблемою одного з наших брандмауерів, де він міг обробляти пропускну здатність у перерахунку на кбіт / с, але не міг обробити кількість пакетів за секунду, які він отримував. Він перевищував 140 000 пакетів в секунду. Деякі швидкі математики на вашому abзапуску змушують мене повірити, що ви бачили б близько 13000 пакетів в секунду (ігноруючи 5% повільних запитів). Можливо, це вузьке місце, якого ви досягли. Те, що це відбувається близько 256, може бути суто збігом обставин.

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