Назад | Перейти на главную страницу

Apache достигает MaxClients и блокирует сервер

В настоящее время у меня есть сервер Apache2, работающий с mpm-prefork и mod_php на OpenVZ VPS с 512 МБ реальной / 1024 МБ оперативной памяти (без подкачки). Проведя несколько тестов, я обнаружил, что максимальный размер процесса, который получает Apache, составляет 23M, поэтому я установил MaxClients до 25 (23M x 25 = 575 МБ, для меня нормально). Я решил провести несколько нагрузочных тестов на своем сервере, и результаты меня озадачили.

я использую ab на моем настольном компьютере запрашивая главную страницу из блога wordpress.

Когда я бегу ab с 24 одновременными подключениями вроде все нормально. Конечно, ЦП увеличивается, свободная оперативная память уменьшается, и в результате время отклика на запрос составляет около 2-3 секунд.

Но если я убегу ab при 25 одновременных подключениях (ограничение на мой сервер) Apache просто зависает через пару секунд. Он начинает обрабатывать запросы, затем перестает отвечать, ЦП возвращается в режим ожидания 100% и ab время вышло. Журнал Apache говорит, что достиг MaxClients.

Когда это происходит, Apache остается заблокированным с 25 запущенными процессами (все они в "W", если я проверяю состояние сервера) и только после TimeOut установка процессов начинает умирать, и сервер снова начинает отвечать (в моем случае он установлен на 45).

Мой вопрос: это ожидаемое поведение? Почему Apache просто умирает, когда достигает MaxClients? Если он работает с 24 соединениями, не должен ли он работать с 25, просто тратя больше времени на ответ на каждый запрос и постановку остальных в очередь?

Мне кажется странным, что бегущий ребенок ab может в одиночку убить веб-сервер, просто установив одновременные подключения к серверам MaxClients.

ХА! Наконец-то я сам нашел проблему. Это больше связано с программированием, чем с администратором сервера, но я все равно решил поставить ответ здесь, потому что, выполнив поиск в Google, я обнаружил, что я не единственный, у кого такая проблема (и поскольку Apache зависает, первое предположение заключается в том, что есть проблема с сервером).

Проблема не в Apache, а в моем Wordpress. Точнее с моей темой. Я использую тему под названием Lightworld, и она поддерживает добавление изображения в заголовок блога. Для этого он проверяет размер изображения с помощью функции PHP getimagesize(). Поскольку эта функция открывала другое http-соединение с сервером для получения изображения, каждый запрос от ab создавал другой запрос внутри PHP. Поскольку я использовал все доступные слоты моего сервера, эти запросы PHP были помещены в очередь, но Apache никогда не мог до них добраться, потому что все его процессы были заблокированы исходным запросом, ожидающим, пока слот завершит внутренний запрос PHP.

По сути, PHP переводил мой сервер в состояние тупика, и Apache начинал нормально работать только после того, как эти соединения истекали в ожидании своего «дочернего» запроса.

После того, как я удалил эту функцию из своей темы, теперь я могу ab у моего сервера столько одновременных подключений, сколько я хочу, и Apache ставит их в очередь, как и ожидалось.

Здесь происходит то, что у вас есть 25 потоков, способных принимать соединения, и вы отправляете 26 одновременных запросов. Этот последний запрос находится в очереди сокетов в зависимости от размера вашего невыполненного журнала.

Вторая проблема заключается в том, что все, что вы запускаете, занимает 2-3 секунды, но требует времени, чтобы ответить, что 25 одновременных подключений замедляют его. sleep (1) может работать, но что-то, где вы выполняете блокировку файлов или блокировку таблицы из mysql, каждый параллельный запрос может ожидать своего завершения до тех пор, пока не достигнет 45-секундного тайм-аута.

23 МБ звучит мало для процесса apache с mod_php и любыми загруженными модулями, поэтому я подозреваю, что вы могли видеть, что эти процессы apache занимают немного больше оперативной памяти во время работы вашего приложения. Вы не можете заниматься математикой с MaxClients и такой памятью ... это будет несколько близко, но вы никогда не знаете.

www-data  1495  0.1  0.9  56288 19996 ?        S    15:48   0:01 /usr/sbin/apache2 -k start
www-data  1500  0.0  0.5  49684 12436 ?        D    15:48   0:00 /usr/sbin/apache2 -k start

Есть одна машина, 56M и 49M процессов.

другая машина:

www-data  7767  0.1  0.1 213732 14840 ?        S    14:55   0:08 /usr/sbin/apache2 -k start
www-data  8020  0.2  0.1 212424 13660 ?        S    14:57   0:08 /usr/sbin/apache2 -k start

другая машина:

www-data 28509  0.8  0.1 161720 10068 ?        S    14:39   0:43 /usr/sbin/apache2 -k start
www-data 28511  0.8  0.1 161932 10344 ?        S    14:39   0:43 /usr/sbin/apache2 -k start

Итак, использование памяти очень зависит от задачи, какие модули загружены и т. Д. В последних двух, я считаю, мы отключили pdo и pdo_mysql, поскольку это приложение их не использует.

Настоящий вопрос в том, что вы делаете, на что уходит 3 секунды? В современном мире это вечность и считается «блокирующим» приложением. Apache обычно не умирает, но оставит эти потоки в очереди невыполненных работ, пока не сможет их обслужить или пока не истечет время ожидания запросов. Я считаю, что ваше приложение, вероятно, вызывает тайм-аут apache. Попробуйте это на странице, содержащей только phpinfo (); и посмотрите, совпадают ли результаты.