Как я победил ошибку 502 Gateway timeout error в nginx+php-fpm

Php-fpm считается на сегодняшний день одним из самых быстрых движков для веб-сервера. Но он очень нестабилен при работе со сложным php-кодом. И в один прекрасный день вы можете получить ошибку 502 Gateway timeout error.

У меня в проекте так и получилось. На VPS стоял nginx + php7.0-fpm + MariaDB + memcached. Код php-скрипта использовал весь этот стэк технологий и работал благополучно пару месяцев, а потом вдруг стал выдавать 502-ю.

Для проверки, когда мой скрипт все-таки работает, я написал скрипт-чекер на php и запускал каждые 10 минут его по сron. Чекер запускался через консоль, а обращался через функцию file_get_contents() к url скрипта на сайте. В случае недоступности скрипта я отсылал через mail() письмо себе на почту.

Я выяснил, что ошибка 502 Gateway timeout error возникала не всегда. Могла появиться раз в час, а могла и на протяжении многих часов. Временно исправить проблему помогала перезагрузка nginx и memcached.

Почитав мануалы, я решил применить то, что советуют – увеличить proxy timeout в директиве Location, а также timeout в настройках php-fpm. Не помогло. Причем, когда я вообще сделал timeout в php-fpm бесконечным, скрипту все равно не хватало времени и он выполнялся без конца.

Решив, что все-таки дело в php-fpm я подумал, чем же его заменить. Порывшись в интернете я нашел решение для замены – OpenLightSpeed Webserver + php-модуль к нему.

Установив этот вебсервер, что было не совсем просто, но все же осуществимо в конце концов я обнаружил, что 502-я ошибка появляется все также. Еще я не смог настроить BasicAuth авторизацию на папках, поэтому недолго думая запустил восстановление бэкапа диска VPS-сервера и через 10 минут снова работал с nginx+php-fpm.

Последнее обстоятельство толкало на новую мысль – дело не в сервере, а в скрипте. И это оказалось правильным. Я залез в скрипт – там было 5 sql-запросов к mysql. 2 я слил в 1 при помощи LEFT JOIN, из 2-х запросов сделал 1 и еще 1 оставил как есть. Исследуя запросы, я обратил внимание на запрос SELECT max(price) FROM prices WHERE session_id = ‘1’ и решил залезть в phpmyadmin, чтобы посмотреть таблицы.

Каково было мое удивление, когда я обнаружил 400000 записей цен. При этом для этой таблицы не было установлено ни одного индекса. Все. Причины ошибки 502 были найдены! Был переписан скрипт импорта записей в таблицу цен, а в самой таблице цен созданы индексы.

После проведения работ теперь все работает как надо.

Возможно, что при появлении ошибки 502 Gateway timeout error причина может быть в базе данных и в веб-сервере, а совсем не в php-fpm. Поэтому в базе данных можно попробовать включить лог медленных запросов (slow query), а в веб-сервере промониторить, появляется ли 502-я ошибка при получении с сервера статических файлов – картинок или css-стилей.

Комментарии

комментарии

Написать комментарий