Наденьте очки для чтения - они будут надолго.
Во-первых, что я делаю. Я создаю интерфейс веб-приложения для некоторых особенно медленных tcp-устройств. Открытие сокета для них занимает 200 мс, а цикл fwrite / fread занимает еще 300 мс. Чтобы уменьшить необходимость в обоих этих действиях при каждом запросе, я открываю постоянный TCP-сокет, который сокращает время ответа на вышеупомянутые 200 мс. Я надеялся, что PHP-FPM будет совместно использовать постоянные соединения между запросами от разных клиентов (и это действительно так!), Но есть некоторые проблемы, которые я не смог решить после 2 дней выхода в Интернет, чтения журналов и изменения настроек. Хотя я несколько сузил его.
Настроить:
Relevent config:
nginx
php-fpm / pool.d
Давайте перейдем от грубых к мелким деталям того, что происходит. После нового старта у меня есть 4 процесса nginx и 2 процесса php5-fpm, ожидающие обработки запросов. Затем каждые пару секунд я отправляю скрипту запросы. Первому требуется время, чтобы открыть соединение сокета и вернуть данные примерно через 500 мс, второй возвращает данные за 300 мс (да, он повторно использует сокет), третий также успешно работает примерно через 300 мс, четвертый запрос = 502 Bad Gateway , то же самое с 5-м. Шестой запрос снова возвращает данные, только теперь он снова занял 500 мс. Процесс повторяется в течение нескольких циклов, после которых каждые 4 запроса приводят к ответам 2x 502 Bad Gateways и 2x 500ms Data.
Если я удваиваю все значения пула fpm и выполняю 4x процесса php-fpm, циклы устанавливаются с 4x успешными ответами 500 мс, за которыми следуют 4x ошибки Bad Gateway. Если я не использую постоянные сокеты, эта проблема исчезнет, но тогда каждый запрос составляет 500 мс. Я подозреваю, что происходит постоянный сокет, который удерживает каждый процесс php-fpm от холостого хода и связывает его, поэтому выбирается следующий, пока не останется ни одного, и, когда они выйдут из строя, возможно, они будут перезапущены и станут доступными в следующем раунде - robin loop, но сокет умирает вместе с процессом. Я еще не проверял "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" при почти нулевой нагрузке (на тестовом сервере)
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/#Heading3
https://stackoverflow.com/questions/242316/how-to-keep-a-php-stream-socket-alive
я сообщил об этой проблеме в списке рассылки. это закончилось ошибкой в php, которая теперь решена в git, должна быть в следующей версии php, w00t!
если кому интересно: https://groups.google.com/forum/#!topic/highload-php-en/qGu3Eaifj9s