В настоящее время у меня есть сервер 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 (); и посмотрите, совпадают ли результаты.