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

9

Я в настоящее время сервер Apache2 работает с mpm-preforkи mod_phpна OpenVZ VPS с 512M реальной / 1024M Burstable RAM (без замены). После запуска некоторых тестов я обнаружил, что максимальный размер процесса, который получает Apache, составляет 23 MaxClientsМБ, поэтому я установил значение 25 (23 М 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.

Родриго Сийру
источник

Ответы:

17

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

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

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

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

Родриго Сийру
источник
Спасибо за то, что опубликовали это здесь, я пытался выяснить проблему с точно такими же симптомами в течение нескольких дней - думаю, у нас тоже есть тупиковая ситуация!
Джеймс Йель
как вы это определили, меня в первую очередь интересуют журналы и инструменты, которые вы использовали для определения вторичного исходящего запроса.
Анируд Гоэль
2

Здесь происходит то, что у вас есть 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 (); и посмотреть, если результаты одинаковы.


источник
Спасибо за все советы! Я знаю, что мне все еще нужно оптимизировать многие вещи (я только начал настраивать сервер пару дней назад, и это мой первый опыт работы с VPS), но проблема была еще глубже ... Я отправил ответ на Вопрос, объясняющий, в чем была проблема в моем конкретном случае.
Родриго Сийру