Я управляю сайтом с относительно низким трафиком, который посещает один раз в неделю после обновления сайта. Во время этого скачка производительность сайта очень низкая по сравнению с остальной частью недели. Фактически нагрузка на серверы остается очень низкой, надежно ниже 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)
Эти два теста вместе поднимают ряд вопросов, но отдельно от этого, теперь есть веские аргументы в пользу некоторого серьезного узкого места в сети, возникающего при определенной величине нагрузки. Я думаю, что следующие шаги будут исследовать сетевой уровень отдельно.
источник
Ответы:
Что бы я сделал в этой ситуации, это запустить
на одном из ваших процессов Apache во время теста ab, пока вы не захватите один из медленных ответов. Тогда посмотрите
trace.txt
.-tt
И-T
опции дают вам метки времени начала и продолжительности каждого системного вызова , чтобы помочь идентифицировать медленные.Вы можете найти один медленный системный вызов, такой как
open()
или,stat()
или вы можете найти быстрый вызов с (возможно, несколькими)poll()
вызовами непосредственно после него. Если вы обнаружите, что оно работает с файловым или сетевым соединением (вполне вероятно), посмотрите в обратном направлении, пока не найдете этот файл или дескриптор соединения. Более ранние вызовы этого же дескриптора должны дать вам представление о том, чегоpoll()
ожидал.Хорошая идея, глядя на
-c
вариант. Удалось ли вам убедиться, что отслеживаемый вами ребенок Apache обслуживал хотя бы один из медленных запросов за это время? (Я даже не уверен, как ты это сделаешь, кромеstrace
одновременной работы со всеми детьми.)К сожалению,
strace
не дает нам полной картины того, что делает работающая программа. Он только отслеживает системные вызовы. Многое может произойти внутри программы, которая не требует от ядра запроса чего-либо. Чтобы выяснить, происходит ли это, вы можете посмотреть метки времени начала каждого системного вызова. Если вы видите значительные пробелы, то время уходит. Это не легко понять, и всегда есть небольшие промежутки между системными вызовами.Поскольку вы сказали, что загрузка ЦП остается низкой, между системными вызовами , вероятно, не происходит чрезмерных вещей, но стоит проверить.
Присмотревшись более внимательно к выходным данным
ab
:Внезапный скачок времени отклика (похоже, что время отклика между 150 мс и 3000 мс не существует) указывает на то, что где-то происходит определенный тайм-аут, который срабатывает выше примерно 256 одновременных соединений. Можно ожидать более плавной деградации, если у вас заканчивается ОЗУ или ЦП выполняет нормальный ввод-вывод.
Во-вторых, медленный
ab
ответ показывает, что 3000 мс были потрачены вconnect
фазе. Почти все они заняли около 30 мс, но 5% - 3000 мс. Это говорит о том, что проблема в сети.Откуда ты бежишь
ab
? Можете ли вы попробовать это из той же сети, что и машина Apache?Для получения дополнительных данных попробуйте запустить
tcpdump
на обоих концах соединения (желательно сntp
запуском на обоих концах, чтобы вы могли синхронизировать оба захвата.) И ищите все повторные передачи tcp. Wireshark особенно хорош для анализа дампов, потому что он выделяет повторные передачи tcp другим цветом, облегчая их поиск.Возможно, стоит также посмотреть журналы любых сетевых устройств, к которым у вас есть доступ. Недавно я столкнулся с проблемой с одним из наших брандмауэров, где он мог обрабатывать пропускную способность в терминах кбит / с, но он не мог обрабатывать количество пакетов в секунду, которые он получал. Это превысило 140 000 пакетов в секунду. Некоторая быстрая математика на ваших
ab
потенциальных клиентах заколите меня поверить , что ты был бы увидеть около 13 000 пакетов в секунду ( не обращая внимания на 5% медленных запросы). Может быть, это узкое место, которое вы достигли. Тот факт, что это происходит около 256, может быть просто совпадением.источник