php-fpm + постоянные сокеты = 502 плохих шлюза

Наденьте очки для чтения - это будет долго.

Во-первых, что я делаю. Я создаю интерфейс веб-приложения для некоторых особенно медленных устройств TCP. Открытие сокета для них занимает 200 мс, а цикл fwrite/fread - еще 300 мс. Чтобы уменьшить потребность в обоих этих действиях для каждого запроса, я открываю постоянный сокет tcp, который сокращает время ответа на вышеупомянутые 200 мс. Я надеялся, что PHP-FPM разделит постоянные соединения между запросами от разных клиентов (и это действительно так!), Но есть некоторые проблемы, которые мне не удалось решить после 2 дней работы в Интернете, чтения журналов и изменения настроек. Я несколько сузил это все же.

Настроить:

  • Сервер Ubuntu 13.04 x64 (полностью обновленный) на Linode
  • PHP 5.5.0-6 ~ raring + 1 (fpm-fcgi)
  • Nginx/1.5.2

Удалить конфигурацию:

Nginx

  • рабочий_процесс 4;

PHP-FPM / pool.d

  • pm = динамический
  • pm.max_children = 2
  • pm.start_servers = 2
  • pm.min_spare_servers = 2

Давайте перейдем от грубой к мелкой детали того, что происходит. После нового запуска у меня 4x процесса nginx и 2x php5-fpm, ожидающих обработки запросов. Затем я посылаю запросы каждые пару секунд к сценарию. Первая занимает некоторое время, чтобы открыть соединение с сокетом и возвращает данные примерно через 500 мс, вторая возвращает данные за 300 мс (да, это повторное использование сокета), третья также успешно выполняет около 300 мс, четвертый запрос = 502 Bad Gateway То же самое с 5-го. Шестой запрос снова возвращает данные, за исключением того, что теперь снова потребовалось 500 мс. Процесс повторяется в течение нескольких циклов, после чего каждые 4 запроса приводят к получению 2x 502 неверных шлюзов и 2x 500 мсек данных.

Если я удваиваю все значения пула fpm и запускаю 4x процесса php-fpm, циклы устанавливаются с 4x успешными ответами 500 мс, за которыми следуют 4x ошибки Bad Gateway. Если я не использую постоянные сокеты, эта проблема исчезнет, ​​но каждый запрос будет 500 мс. Я подозреваю, что постоянный сокет удерживает каждый процесс php-fpm от холостого хода и связывает его, поэтому следующий выбирается до тех пор, пока не останется ни одного и, как только произойдет ошибка, возможно, они будут перезапущены и станут доступны в следующем раунде. Цикл Робина, но сокет умирает вместе с процессом. Я еще не проверил "slowlog", но журнал ошибок nginx показывает многое из этого:

* 188 recv() не удалось (104: сброс соединения по одноранговому узлу) при чтении заголовка ответа из восходящего потока, клиент:...

Все предложения в Интернете, касающиеся исправления плохого шлюза nginx/php-fpm/502, относятся к высокой нагрузке или неправильной конфигурации fcgi_pass. Это не тот случай, здесь. Увеличение буферов / размеров, изменение тайм-аутов, переключение с сокета unix на сокет tcp для fcgi_pass, повышение ограничений на соединения в системе... здесь все это не применимо.

У меня был некоторый другой успех с установкой pm = ondemand, а не динамической, но как только начальный процесс fpm был убит после простоя, постоянный сокет пропал для всех последующих порождений php-fpm. Для сценария php я использую stream_socket_client() с флагом STREAM_CLIENT_PERSISTENT. Цикл while/stream_select() для обнаружения данных сокета и fread($sock, 4096) для получения данных. Я не вызываю fclose(), очевидно.

Если у кого-то есть дополнительные вопросы или советы о том, как получить постоянный сокет, не связывая процессы php-fpm после завершения запроса, или, может быть, есть другие вещи, которые стоит попробовать, я был бы признателен.

несколько полезных ссылок:

Nginx + php-fpm - ошибка recv()

Nginx + php-fpm "504 Gateway Time-out" ошибка с почти нулевой нагрузкой (на тест-сервере)

Nginx + PHP-FPM "ошибка 104 Сброс соединения по пиру" вызывает случайные повторяющиеся сообщения

http://www.linuxquestions.org/questions/programming-9/php-pfsockopen-552084/

https://stackoverflow.com/questions/14268018/concurrent-use-of-a-persistent-php-socket

http://devzone.zend.com/303/extension-writing-part-i-introduction-to-php-and-zend/

https://stackoverflow.com/questions/242316/how-to-keep-a-php-stream-socket-alive

http://php.net/manual/en/install.fpm.configuration.php

https://www.google.com/search?q=recv%28%29+failed+%28104:+Connection+reset+by+peer%29+while+reading+response+header+from+upstream+%22502%22&ei = & mC1XUrm7F4WQyAHbv4H4AQ начать = 10 & са = N & BIW = 1920 & БиГ = 953 & DPR = 1

1 ответ

Решение

Я сообщил об этой проблеме в списке рассылки. в итоге это была ошибка в php, которая теперь разрешена в git, должна быть в следующей версии php, w00t!

если кому-то интересно, https://groups.google.com/forum/

Другие вопросы по тегам