Я розміщую відносно низький трафік сайту, який відчуває великий сплеск відвідувачів раз на тиждень після оновлення сайту. Під час цього сплеску продуктивність сайту надзвичайно погана порівняно з рештою тижня. Фактично навантаження на сервери залишається дуже низькою, надійно під 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)
Ці два тести разом викликають цілу низку питань, але окремо від цього зараз є вагомий випадок для якогось серйозного вузького вузького місця, яке відбувається під певним навантаженням. Я думаю, що наступними кроками буде вивчення мережевого рівня окремо.