Я управляю сайтом с относительно низким трафиком, который посещает один раз в неделю после обновления сайта. Во время этого скачка производительность сайта очень низкая по сравнению с остальной частью недели. Фактически нагрузка на серверы остается очень низкой, надежно ниже 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.
Естественно, я предположил, что это вызвано ограничением потоков в prefork, поэтому я настроил конфигурацию так, чтобы удвоить число доступных потоков и предотвратить ненужное увеличение и уменьшение пула потоков:
<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)
После изучения документации (и Stack Exchange) я в растерянности для дальнейших настроек конфигурации, чтобы попытаться устранить это узкое место. Я что-то упускаю? Должен ли я начать искать ответы за пределами Apache? Кто-нибудь еще видел такое поведение? Любая помощь будет принята с благодарностью.
РЕДАКТИРОВАТЬ:
Согласно совету Ладададада, я столкнулся с Апачем. Я пробовал с -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
(... abdridged)
Если я читаю это правильно (и терпите меня, поскольку я не очень часто использую strace), ни один из системных вызовов не может объяснить количество времени, которое занимают эти запросы. Похоже, что узкое место возникает еще до того, как запросы попадают в рабочие потоки.
РЕДАКТИРОВАТЬ 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)
Эти два теста вместе поднимают ряд вопросов, но отдельно от этого, теперь есть веские аргументы в пользу некоторого серьезного узкого места в сети, возникающего при определенной величине нагрузки. Я думаю, что следующие шаги будут исследовать сетевой уровень отдельно.