Настройка производительности сервера Apache с высокой нагрузкой

12

Я ищу, чтобы понять некоторые проблемы с производительностью сервера, которые я вижу с (для нас) сильно загруженным веб-сервером. Среда выглядит следующим образом:

  • Debian Lenny (все стабильные пакеты + исправлены обновления безопасности)
  • Apache 2.2.9
  • PHP 5.2.6
  • Amazon EC2 большой экземпляр

Поведение, которое мы наблюдаем, состоит в том, что сеть обычно чувствует себя отзывчивым, но с небольшой задержкой, чтобы начать обработку запроса - иногда доли секунды, иногда 2-3 секунды в наше пиковое время использования. Фактическая нагрузка на сервер сообщается как очень высокая - часто 10.xx или 20.xx, как сообщает top. Кроме того, запуск других вещей на сервере в это время (даже vi) очень медленный, поэтому нагрузка определенно там. Как ни странно, Apache остается очень отзывчивым, кроме этой начальной задержки.

Мы настроили Apache следующим образом, используя prefork:

StartServers          5
MinSpareServers       5
MaxSpareServers      10
MaxClients          150
MaxRequestsPerChild   0

И KeepAlive как:

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

Глядя на страницу состояния сервера, даже в эти периоды большой нагрузки мы редко сталкиваемся с ограничениями клиентов, обычно обслуживая от 80 до 100 запросов, и многие из них находятся в состоянии поддержки активности. Это говорит мне, чтобы исключить начальную медлительность запроса как «ожидание обработчика», но я могу ошибаться.

Мониторинг Amazon CloudWatch говорит мне, что даже когда наша ОС сообщает о загрузке> 15, загрузка нашего экземпляра ЦП составляет 75-80%.

Пример вывода из top:

top - 15:47:06 up 31 days,  1:38,  8 users,  load average: 11.46, 7.10, 6.56
Tasks: 221 total,  28 running, 193 sleeping,   0 stopped,   0 zombie
Cpu(s): 66.9%us, 22.1%sy,  0.0%ni,  2.6%id,  3.1%wa,  0.0%hi,  0.7%si,  4.5%st
Mem:   7871900k total,  7850624k used,    21276k free,    68728k buffers
Swap:        0k total,        0k used,        0k free,  3750664k cached

Большинство процессов выглядят так:

24720 www-data  15   0  202m  26m 4412 S    9  0.3   0:02.97 apache2                                                                       
24530 www-data  15   0  212m  35m 4544 S    7  0.5   0:03.05 apache2                                                                       
24846 www-data  15   0  209m  33m 4420 S    7  0.4   0:01.03 apache2                                                                       
24083 www-data  15   0  211m  35m 4484 S    7  0.5   0:07.14 apache2                                                                       
24615 www-data  15   0  212m  35m 4404 S    7  0.5   0:02.89 apache2            

Пример вывода из vmstatтого же времени, что и выше:

procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 8  0      0 215084  68908 3774864    0    0   154   228    5    7 32 12 42  9
 6 21      0 198948  68936 3775740    0    0   676  2363 4022 1047 56 16  9 15
23  0      0 169460  68936 3776356    0    0   432  1372 3762  835 76 21  0  0
23  1      0 140412  68936 3776648    0    0   280     0 3157  827 70 25  0  0
20  1      0 115892  68936 3776792    0    0   188     8 2802  532 68 24  0  0
 6  1      0 133368  68936 3777780    0    0   752    71 3501  878 67 29  0  1
 0  1      0 146656  68944 3778064    0    0   308  2052 3312  850 38 17 19 24
 2  0      0 202104  68952 3778140    0    0    28    90 2617  700 44 13 33  5
 9  0      0 188960  68956 3778200    0    0     8     0 2226  475 59 17  6  2
 3  0      0 166364  68956 3778252    0    0     0    21 2288  386 65 19  1  0

И, наконец, вывод Apache server-status:

Server uptime: 31 days 2 hours 18 minutes 31 seconds
Total accesses: 60102946 - Total Traffic: 974.5 GB
CPU Usage: u209.62 s75.19 cu0 cs0 - .0106% CPU load
22.4 requests/sec - 380.3 kB/second - 17.0 kB/request
107 requests currently being processed, 6 idle workers

C.KKKW..KWWKKWKW.KKKCKK..KKK.KKKK.KK._WK.K.K.KKKKK.K.R.KK..C.C.K
K.C.K..WK_K..KKW_CK.WK..W.KKKWKCKCKW.W_KKKKK.KKWKKKW._KKK.CKK...
KK_KWKKKWKCKCWKK.KKKCK..........................................
................................................................

Из моего ограниченного опыта я делаю следующие выводы / вопросы:

  • Возможно, мы разрешаем слишком много KeepAliveзапросов

  • Я вижу некоторое время, потраченное на ожидание ввода-вывода в vmstat, хотя не постоянно и не так много (я думаю?), Поэтому я не уверен, что это большая проблема или нет, я менее опытен с vmstat

  • Также в vmstat я вижу в некоторых итерациях ряд процессов, ожидающих обслуживания, к чему я приписываю начальную задержку загрузки страницы на нашем веб-сервере, возможно, ошибочно

  • Мы подаем смесь статического контента (75% или выше) и контента скрипта, и контент скрипта часто довольно интенсивно использует процессор, поэтому важно найти правильный баланс между ними; в долгосрочной перспективе мы хотим перенести статику в другое место, чтобы оптимизировать оба сервера, но наше программное обеспечение не готово к этому сегодня

Я рад предоставить дополнительную информацию, если у кого-то есть какие-либо идеи, другое замечание, что это производственная установка с высокой доступностью, поэтому я опасаюсь вносить изменения после настройки, и именно поэтому я сам не играл с такими вещами, как KeepAliveценность еще.

futureal
источник
+1 Кровавый отличный вопрос, хорошо сформулированный и продуманный. Надеюсь, вы получили ответ, которого он заслуживает!
Дэйв Рикс

Ответы:

7

Начну с того, что признаюсь, что мне не очень нравится запускать что-то в облаках, но, основываясь на моем опыте в других местах, я бы сказал, что эта конфигурация веб-сервера отражает довольно низкий объем трафика. То, что очередь выполнения настолько велика, говорит о том, что процессору просто не хватает для ее решения. Что еще в очереди?

Возможно, мы разрешаем слишком много запросов KeepAlive

Нет - keeplive по-прежнему повышает производительность, современные браузеры очень хорошо знают, когда выполнять конвейеризацию и когда выполнять запросы параллельно, хотя время ожидания в 5 секунд все еще довольно велико, и у вас МНОГО серверов, ожидающих - если вы не ' У меня ОГРОМНЫЕ проблемы с задержкой, я бы рекомендовал довести это до 2-3. Это должно немного сократить runqueue.

Если вы еще не установили mod_deflate на веб-сервере - тогда я бы порекомендовал вам сделать это - и добавьте ob_gzhandler () в ваши PHP-скрипты. Вы можете сделать это в качестве авто-предоплаты:

if(!ob_start("ob_gzhandler")) ob_start();

(да, для сжатия используется больше ЦП - но вы должны экономить ЦП в целом, быстрее выводя серверы из очереди выполнения / обрабатывая меньше пакетов TCP - и в качестве бонуса ваш сайт также быстрее).

Я бы рекомендовал установить верхний предел для MaxRequestsPerChild - скажем, около 500. Это просто обеспечивает некоторый оборот процессов в случае, если у вас где-то есть утечка памяти. Ваши процессы httpd выглядят ОГРОМНЫМИ - убедитесь, что вы удалили все ненужные модули apache, и убедитесь, что вы обслуживаете статический контент с хорошей информацией о кэшировании.

Если вы все еще видите проблемы, то проблема, вероятно, в коде PHP (если вы переключитесь на использование fastCGI, это должно быть очевидно без какого-либо существенного снижения производительности).

Обновить

Если статический контент не сильно отличается на разных страницах, возможно, стоит поэкспериментировать с:

if (count($_COOKIE)) {
    header('Connection: close');
}

на скриптах PHP тоже.

symcbean
источник
Среди множества хороших ответов я отмечаю это как принятый, потому что вы четко заявили, что это было связано с процессором (в основном из-за плохого приложения, которое мы запускаем), и это, безусловно, имело место. Я перераспределил все на 2 больших экземплярах EC2 (по сравнению с большими), и большинство проблем исчезли, хотя многие другие характеристики производительности все еще присутствуют. У нас только одно приложение, работающее на этих серверах, и оно просто ужасно.
будущий
4

Вам следует рассмотреть возможность установки асинхронного обратного прокси-сервера, поскольку число процессов в состоянии W также достаточно велико. Кажется, что ваши процессы Apache тратят много времени на отправку контента медленным клиентам по сети, заблокированной на этом. Nginx или lighttpd как интерфейс вашего сервера Apache могут значительно сократить количество процессов в состоянии W. И да, вы должны ограничить количество запросов keepalive. Вероятно, стоит попытаться отключить keepalive.

Кстати, 107 процессов Apache слишком высоки для 22 об / с, я смог обслужить 100-120 об / с, используя только 5 процессов Apache. Вероятно, следующим шагом будет профилирование вашего приложения.

Alex
источник
Да, определенно согласился, что приложение является большой частью проблемы. Он был передан на аутсорсинг и с тех пор подвергался множеству исправлений и так далее, что только усугубило ситуацию, и работа по редизайну продолжается. Сегодня вечером я попытался отключить KeepAlive без особого эффекта, и мой следующий шаг - попробовать этот обратный прокси-сервер, вероятно, с nginx, основываясь на всем, что я прочитал.
будущем
Чтобы продолжить, я начал экспериментировать с обратным прокси-сервером и, вероятно, разверну его в ближайшем будущем. Спасибо (и другим, кто это предложил) за эту идею, я никогда не возился с этим раньше, но я думаю, что это окажет влияние, пока мы не сможем сделать полноценный редизайн.
будущий
1

У вас есть две строки в вашем vmstat, которые показывают, что время ожидания вашего процессора довольно велико, и вокруг них вы делаете значительное количество операций записи (io-bo) и переключения контекста. Я бы посмотрел на то, что пишет блоки, и как устранить это ожидание. Я думаю, что наибольшее улучшение можно найти в улучшении дискового ввода-вывода. Проверьте системный журнал - установите его, чтобы написать async. Убедитесь, что кэш записи вашего контроллера работает (проверьте его - возможно, у вас плохой аккумулятор).

Keepalive не вызывает проблем с перфорированием, он экономит ваше время на настройку соединения, если вы не запускаете кеш впереди. Вы можете немного поднять MaxSpareServers, чтобы в кризисе вы не ждали всех вилок.

фасоль
источник
Я не достаточно знаком с системным журналом, чтобы знать, как установить его для асинхронных записей под Apache, хотя я, безусловно, буду искать и искать его. Сегодня вечером я внес некоторые изменения, связанные с KeepAlive и MaxSpareServers, но безрезультатно, я согласен оставить больше запчастей, я пропустил это. Одно (плохое) качество нашего приложения заключается в том, что оно интенсивно записывает в пользовательские файлы сеансов (да, в файлы), и я начинаю думать, что мы страдаем. У меня есть возможность перенести управление сеансами в базу данных, что я, скорее всего, попробую в следующем.
будущие
Да, я согласен с тем, что ваши записи сеанса являются источником проблемы. Вы можете потерять записи сеансового диска, если используете сеансы php - установите memcache и установите для PHP session.save_handler значение memcache, а для session.save_path значение tcp. : //127.0.0.1: 11211 (или где бы вы ни установили memcache). Ведение журнала в Apache является асинхронным по умолчанию, но иногда веб-приложения могут использовать syslog, или syslog может быть болтливым, и он выполняет синхронизацию для каждой строки. В конце концов, это не похоже на проблему в вашем случае. Вы можете использовать префикс строки файла в «syslog.conf», чтобы пропустить синхронизацию.
фасоль
0

Вы должны рассмотреть отключение keepalive в качестве первой попытки ...

с обработкой 107 запросов я бы держал MaxSpareServers выше, чем вы установили ...

ИМХО в долгосрочной перспективе nginx в качестве обратного прокси для статического контента следует учитывать

evcz
источник
0

Первое предложение: отключить keepalive. Мне это было нужно только тогда, когда я мог определить конкретную ситуацию, в которой производительность увеличилась, но в целом количество запросов в секунду уменьшилось при включенном Keepalive.

Второе предложение: установить MaxRequestsPerChild. Я повторяю symcbean здесь, это поможет с опрокидыванием процесса в случае утечки памяти. 500 - хорошая отправная точка.

Третье предложение: увеличить MaxClients. Примерный расчет для этого: (физическая память - память, используемая процессом, отличным от httpd) / размер каждого процесса httpd. В зависимости от того, как был скомпилирован httpd, это число достигает 255. Я использую 250 для своих общедоступных серверов, чтобы справиться с Google / Yahoo / MS, сканирующей системы.

Четвертое предложение: увеличить MaxSpareServers: что-то вроде 4-5x MinSpareServers.

Если не принимать во внимание эти предложения, я бы посмотрел на распределение нагрузки с помощью обратного прокси-сервера или memcache для БД.

Пол С
источник