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

Что может вызывать это прерывистое событие остановки PHP?

Хотел бы я быть более конкретным по этому вопросу, и я действительно прошу совета, где искать дальше.

Мы запускаем веб-приложение PHP, которое интегрировано с WordPress и обслуживает страницу каждую секунду в течение некоторых частей дня. Как правило, все работает очень хорошо на одном выделенном сервере (четырехъядерный с 16 ГБ ОЗУ).

Я подумываю о New Relic, и их инструменты предупреждали меня о периодической загрузке страницы, когда PHP, кажется, зависает. Он достигает, казалось бы, произвольной точки в трассировке вызовов, а затем тратит много секунд (или десятки секунд) на что-то тривиальное. Самым тривиальным примером была функция, которая была условной, за которой следовала echo ().

Я не вижу других ошибок (в журнале ошибок Apache / PHP) или медленных запросов, которые совпадают с этими событиями. Они также, похоже, не совпадают с какой-либо особенно большой загрузкой процессора, дискового ввода-вывода или сетевого ввода-вывода.

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

Linux: CentOS 5.6

Apache: 2.2.3

MYSQL: 5.5

PHP: 5.3.9

APC: 3.1.9 (кеш исправен, частота совпадений близка к 100%)

Как предположил ДжейкГулд, это была проблема конфигурации.

Решением было поднять максимальный размер буфера записи TCP / IP до 256 КБ (до этого было около 128 КБ) и указать, что Apache использует максимум, используя директиву SendBufferSize в модуле prefork в httpd.conf. Это относится к вам, если вы используете префорк в качестве MPM. YMMV с другими MPM.

Причина, по которой это решает проблему:

Иногда мы обслуживаем большие страницы, и когда размер страницы больше, чем размер буфера отправки, Apache отправляет буфер, когда он заполнен, а затем ожидает ответа от клиента перед отправкой остальных. Даже при хорошем сетевом соединении это может вызвать задержку на секунду или две, а при плохом соединении может быть намного хуже. Я думаю, что в действительно патологических случаях (достигающих предела в 120 секунд) пользователь расстроен, уходя со страницы через несколько секунд, поэтому сервер никогда не получает ответа.

Установив размер буфера отправки больше, чем размер большинства страниц, Apache отправляет полную страницу и не ждет ответа.

Конечно, то же самое относится и к отдельным изображениям, которые вы обслуживаете. Если они больше, чем буфер отправки, вы столкнетесь с этой проблемой. Большинство наших изображений обслуживаются CDN, но некоторые из больших изображений, которых нет в CDN, вызывали эту проблему.

Хотя это на самом деле не помогает клиентам с плохим подключением к нашему сайту, оно сократило наше среднее время ответа с 200 мс + до <100 мс. Кроме того, удалив все эти медленные транзакции, я теперь вижу реальные проблемы с производительностью в оставшихся.

PHP FPM SAPI имеет медленный журнал, где скрипты, которые занимают больше времени п секунды можно регистрировать с помощью трассировки. К сожалению, ни один другой SAPI не имеет такой функции. (Если бы вы уже использовали nginx + PHP-FPM, у вас уже было бы это! Это спасло мой бекон не один раз.)

Похоже, что запасным вариантом является запуск xdebug, но в производственной среде это может оказаться непростым делом. Или того хуже, накатить собственные "отладочные" скрипты (см. этот вопрос в Stack Overflow для плохих примеров).