16 марта вышли новые версии php — 7.0.17 и 7.1.3. Это приятная новость для многих php разработчиков, но для нас она приятна еще и тем, что туда вошел наш патч, который чинит keep-alive соединения в php-fpm sapi.

Php-fpm появился сначала как отдельный патч для php 5.2, добавляющий менеджер fastcgi процессов, который позволяет организовать отдельные пулы, следит за временами выполнений рабочих процессов и много другое полезное. В ветке php 5.4 его приняли как официальный sapi и мы избавились от необходимости накладывать этот патч всякий раз, как выходит новая версия php с исправлением ошибок.

У php-fpm есть довольно приятная возможность использовать одно tcp соединения для нескольких последовательных запросов fastcgi — т.н. keepalive. Эта же возможность присутствует и у nginx, который мы используем в качестве fronend http сервера и, соответственно, fastcgi клиента. Использование keepalive сокращает время на установление новых tcp соединений и избавляет от кучи TIME-WAIT записей в таблице tcp.

Мы в 2015 году решили этой возможностью воспользоваться, настроили ее в тестовой среде, провели функциональное тестирование, остались довольны и запустили в боевое применение. Однако, довольно быстро обнаружили, странные записи в php-fpm-slow.log, которые тормозить не могли по своей логике и соответствующие записи в php-fpm.log о том, что рабочие процессы убиваются из-за долгого времени выполнения. Поначалу мы решили, что хорошо, что у нас в nginx в upstream есть backup сервера, все равно http request без response-а не останется, но довольно быстро пришло осознание того, что заголовок ответа уже отправлен, а процесс убит посередине, и пользователи приедет половина страницы.

Через полдня исследования проблемы, чтения кода и наблюдения происходящего в gdb выяснилась смешная ситуация. При keepalive в начале нового fastcgi запроса не сбрасывался счетчик потраченного времени на ноль. Я создал баг-репорт, предложил для него патч и отправил pull request в их репозиторий на github. Pull-request был на ветки 5.5 и 5.6, мы их в то время использовали.

Через некоторое время на мой pull-request разработчики ответили отказом, т.к. эти ветки уже были заморожены и в них изменения вносились только связанные с безопасностью. Зато через 2 года проснулись и предложили внести изменения в ветки 7.0 и 7.1. Я сначала решил, что все уже давно “пофиксено до нас”, но нашлись люди, которые подтвердили существование проблемы. Фикс, как и раньше, оказался в несколько строк.

Сейчас наша конфигурация nginx выглядит примерно так:


http {
...
upstream main {
server 10.20.30.10:9001 max_fails=10 fail_timeout=10s;
server 10.20.30.20:9001 max_fails=10 fail_timeout=10s;
server 10.20.30.30:9001 max_fails=10 fail_timeout=10s backup;
keepalive 32;
}

server {

location ~ (\.php)$ {
fastcgi_pass   main;
fastcgi_keep_conn on;

}
}

TL; DR: если вы раньше использовали keep-alive в fastcgi и испытывали от этого дискомфорт, или если боялись его использовать раньше, то сейчас, с выходом новых версий php самое время начать это делать, это сэкономит ваши нервы и ресурсы сервера.

  • Sharing

    Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather