[Sysadmins] apache tuning in nginx presence

Denis Smirnov =?iso-8859-1?q?mithraen_=CE=C1_freesource=2Einfo?=
Ср Авг 22 15:16:24 MSD 2007


20.08.07, Michael Shigorin<mike на osdn.org.ua> написал(а):

> Если традиционно предлагается[1] поднимать в заметной мере
> параметры, отвечающие за количество свободных серверов,
> то в случае приёма соединений nginx этот подход, похоже,
> менее полезен и может быть вредным (увеличивается scheduling
> overhead).

Именно так. Есть одно принципиальное исключение -- надо учитывать
latency. То есть если по каким-то причинам время выдачи одним апачем
ответа существенно большое на отдельных страницах, то количество
бэкендов приходится увеличивать.


> MinSpareServers 5
> MaxSpareServers 20
> StartServers 12
> MaxClients 12

Везет... мне StartServer 50 надо было делать, а MaxClients 100 на
одном их хостов не хватало... А когда я их увеличил оказалось что надо
поднимать и в MySQL лимиты.

> и это было близко к оптимуму, то в случае, когда неспешные
> коннекшны отрабатывает мультиплексирующий nginx, нам гораздо
> интересней снизить scheduling overhead путём понижения количества
> процессов, между которыми будет распределяться процессорное время:
> MinSpareServers 1
> MaxSpareServers 2
> StartServers 3
> MaxClients 4

Что-то вроде. Правда логику по которой надо рассчитывать оптимум для
этих значений я так и не смог продумать.

> Time per request:       5505.80 -> 4478.60 [ms] (mean)

А что так дофига?

> Requests per second:    3.63 -> 4.47 [#/sec] (mean)
> Time per request:       275.29 -> 223.93 [ms] (mean, across all concurrent requests)
>
> Percentage of the requests served within a certain time (ms)
>   50%   4785 -> 4285
>   66%   5825 -> 4472
>   75%   6879 -> 4610
>   80%   7076 -> 4681
>   90%   8408 -> 4826
>   95%   9112 -> 5005
>   98%   9587 -> 5071

Я правильно понимаю, что это 5 секунд на ответ? И что только 50%
успевают получить ответ за 4 секунды?

>   99%   9656 -> 5136
>  100%  11491 -> 5276 (last request)
>
> При этом MySQL настроен по соотносящейся части так[2]:
>
> thread_cache = 8
> thread_concurrency = 2
>
> Настройка ставила своей целью наличие не менее двух потенциально
> конкурентных процессов на одно процессорное ядро согласно общей
> практике расчёта оптимальной загрузки системы,

Тут есть тонкость -- не все процессы хотят проц, многие хотят всего
лишь диск. Особенно касаемо MySQL. Именно поэтому я пока остановился
на логике "4 треда на ядро".

> но при этом
> в отличие от обычных рекомендаций -- была направлена на разумную
> минимизацию количества конкурирующих экземпляров httpd, которые
> в данной постановке задачи занимаются почти исключительно работой
> с веб-приложением, а не дисковым или сетевым I/O и таким образом
> конкурируют практически исключительно за CPU и RAM.

Дисковым I/O они не будут заниматься исключительно когда ты сделаешь
все на FastCGI каком. А пока у тебя на один запрос минимум:
а) прочитать код скрипта;
б) попытаться прочитать .htaccess (если он не отключен);
в) попытаться прочитать .htacces во всей иерархии каталогов до текущего;
г) намусорить в лог;

Далее, если используется PHP, то мы ещё обычно грузим все include'ы (а
если не грузим потому как умные и юзаем кэши, то тогда как минимум
stat на все include'ы по всей цепочке).

> Т.е. ограничение количества наиболее активных процессов до двух
> на ядро позволило выиграть примерно 10% латентности по нижней
> границе и более 50% -- по верхней.

А вот это бесспорно. nginx отлично справляется с сериализацией потоков
запросов. Собственно на том самом сайте где то установки nginx не
справлялось 100 дочек апача, сейчас их трудится несколько штук.

> Нагрузка выглядит как две пары httpd:mysql с распределением
> потребления процессора примерно как 10:1 на каждое ядро;
> уменьшение MaxClients до двух с тем, чтобы ещё снизить
> конкуренцию, принесло ~10% уменьшение верхней границы (100%),
> но при этом примерно на ту же величину подняло нижнюю границу.

Ты ещё обрати внимание на то, что на сайте обычно находятся страницы
которые исполняются сильно разное количество времени. И вот они могут
здорово тормозить всех остальных.

В теории необходимо их выносить и обслуживать отдельным апачем, и
nginx разруливать по разным апачам обращения к разным страницам.

> PPS: ещё надеюсь, что не открыл америку через Форточку :)

Вообще знание этих фактов позволяет заточить конфиги под один
конкретный сайт чтобы он летал со скоростью света. А вот придумать
более-менее универсальную схему крайне сложно. Мало того, я осмелюсь
утверждать что это практически невозможно.

Я как-то развлекался с идеей спроектировать особо шустрый хостинг для
особо сложных проектов. Так вот все закончилось на том, что либо с
самого начала проектирования сайта в процессе участвует головастый
товарищ, который каждые две секунды пинает всех по поводу того как
правильно писать код с точки зрения производительности, либо можно
слегка (в разы) поднять производительность силами грамотного админа
(который попытается порезать сайт на подсайты, натравить несколько
апачей на один и тот же сайт, разрулить между ними обращения со
стороны nginx, а дальше непрерывно мониторить и крутить настройки).

> [1] http://people.redhat.com/alikins/system_tuning.html
> [2] http://fly.osdn.org.ua/~mike/docs/mysql-tuning.txt


Подробная информация о списке рассылки Sysadmins