Статьи

Автор: Дмитрий Котеров
Опубликована: 26 мая 2008, dklab.ru/chicken/nablas/50.html

Заметки про фронтенды, бэкенды, балансировщики и тому подобное

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

Дополнительные расходы, снижающие скорость

Эффект значительного ускорения загрузки кода, описанный в предыдущей набле, действительно имеет место. (Кстати, если вы еще не прочитали эту статью, рекомендую сделать это прямо сейчас, иначе может быть непонятно, о чем пойдет речь.) Однако из-за того, что после завершения скрипта Apache (или FastCGI PHP — не важно) тратит какое-то время на очистку памяти и ресурсов, в действительности ускорение при больших нагрузках оказывается несколько меньше. А именно, удается добиться ускорения «всего-то» в 13 раз. Вот результаты команды ab -c 5 -n 100 http://example.com/test.php на четырехядерной машине (Linux), любезно предоставленные другом:

  • Чистый PHP без акселераторов:
    • когда файлы грузятся по отдельности: Requests per second: 3.69 [#/sec] (mean)
    • когда файлы слиты в один 5-мегабайтный: Requests per second: 4.85 [#/sec] (mean)
  • PHP с подключенным xCache:
    • когда файлы грузятся по отдельности: Requests per second: 9.41 [#/sec] (mean)
    • когда файлы слиты в один 5-мегабайтный: Requests per second: 34.54 [#/sec] (mean)
  • PHP с подключенным eAccelerator:
    • когда файлы грузятся по отдельности: Requests per second: 14.04 [#/sec] (mean)
    • когда файлы слиты в один 5-мегабайтный: Requests per second: 42.86 [#/sec] (mean)

По просьбам с форума в тесте еще участвовал другой акселератор, xCache, но видно, что лучших результатов он не дал. Общий выигрыш составляет 13 раз (43 запроса в секунду против исходных 3.7). Если же мерять время, которое проходит внутри скрипта на загрузку кода, то получается все тот же 22-кратный выигрыш.

Эффект экономии памяти и «медленных» клиентов

Люди, применяющие FastCGI в PHP, часто смешиваются две проблемы:

  1. Проблема ускорения работы PHP и времени загрузки кода.
  2. Проблема «медленных клиентов».

Предыдущая набла про первый пункт исключительно.

Что касается второго пункта, скажу о нем чуть подробнее, дабы отделить мух от котлет. «Медленный клиент» — это соединение, которое открывает браузером, скажем, dialup-пользователь, и которое из-за этого "висит" по 5-6 секунд, заставляя работающий процесс apache ждать. Или же клиент закачивает большой файл. Закачка может занять несколько минут, и все это время апач будет висеть в памяти и ждать.

Из-за «медленных» клиентов увеличивается необходимое число одновременно работающих процессов с mod_php и, соответственно, расходы памяти. Если применяется FastCGI (например, в nginx), то данная проблема решается автоматически: ведь nginx не соединяется с PHP-процессом до тех пор, пока клиент не передаст данные полностью, и разъединяется сразу же, забрав в свой буфер ответ от PHP-сервера, отдавая его затем браузеру «в фоновом режиме», не задерживая PHP.

Так вот, проблема медленных соединений можно легко решать отдельно, установив так называемый reverse proxy (тот же nginx, lighttpd, pound и т. д.) над Apache. Reverse proxy работает следующим образом: он ждет соединения с клиентом, а когда тот полностью передал данные, быстро открывает соединение с сервером, посылает туда данные, забирает ответ в свой буфер и уже отдает его медленному клиенту так долго, как тот этого хочет (при зтом сервер не блокируется и может обрабатывать уже другие запросы). Таким образом, reverse proxy делает «медленных клиентов» быстрыми.

Часто делают, чтобы именно reverse proxy упаковывал трафик в SSL, а веб-серверы ничего об SSL не знают и отдают контент неупакованным (для улучшения производительности).

Когда используют nginx + FastCGI-PHP, эта связка одновременно как бы является и сервером, и reverse proxy для снижения числа одновременных соединений. Т.е. и мухи, и котлеты — в одном месте. Люди часто это не понимают и считают, что «это nginx такой быстрый сервер», хотя в действительности дело просто в технологии «убыстрения» медленных клиентов, которую можно сделать любыми другими инструментами.

Эту же проблему с «медленными клиентами» имеют в виду, когда говорят «статику надо отдавать nginx-ом». Статика сама по себе вообще не является проблемой: даже самый захудалый apache на самой захудалой машине способен обрабатывать несколько тысяч статических запросов в секунду. Если у вас не фотохостинг, этого достаточно за глаза: как вы понимаете, отдавать 10000 запросов статики в секунду через apache или 11000 запросов в секунду через nginx (т.к. нагрузка идет в основном на диски) — разницы для скорости проекта практически никакой нет. Выигрыш с nginx тут опять только из-за "медленных" клиентов, которые «срезаются» при помощи reverse proxy.

Итак, если ставится несколько апачей, а над ними — один reverse proxy + балансировщик (nginx и pound умеют не только проксировать, но еще и распределять запросы по нескольким машинам), можно особенно не думать насчет какой-то особенной отдачи статики. Можно ее отдавать теми же самыми апачами. Из-за того, что все соединения стали «быстрыми», разница будет совсем маленькой.

Случаи с фотохостингом или сервисом генерации географических карт я не рассматриваю, там все по-другому.

Еще один плюс в использовании машин Apache+mod_php и отдельного reverse proxy над ними — это то, что в Apache имеется модуль mod_status, который подробно показывает, чем сейчас занимается сервер. К сожалению, для FastCGI-версии PHP такой утилиты нет.

Все комментарии