На веб-сервере, который обычно довольно хорошо работает с nginx
и php-fpm
(в настоящее время версия 7.0.22, но в основном она не зависит от версии) , бывают случаи, когда возникает ошибка 502 Bad Gateway. В конечном итоге это означает: один из процессов php-fpm
отказал, и nginx
не получает ответа от выбранного процесса.
Мой текущий способ обхода заключается в отслеживании не только процесса php-fpm
, но и вывода страницы PHP. И если это не сработает в течение 4 минут (две неудачные попытки с интервалом наблюдения 2 минуты), то monit
убьет все процессы php-fpm
и перезапустит php -fpm
сервис. Работает, но по-прежнему вызывает 5-минутный простой (по крайней мере, для некоторых пользователей, которые подключаются к неработающему процессу) или более, потому что monit
может также несколько раз увидеть ответ от нормального процесса, прежде чем он заметит неверный шлюз 502.
(1) Идеальным решением было исправить все, что нарушает процесс php-fpm
. Тем не менее, ошибка возникает редко, поэтому мне не удалось ее отследить по какой-то конкретной причине. Возможно утечка памяти в скрипте PHP ... Я не знаю.
(2) Второй лучший вариант, который я имею в виду, потребует некоторого сотрудничества с nginx
. Если бы процесс веб-сервера мог отреагировать на сбой PHP, он мог бы (а) убить конкретно нарушенный процесс и (б) попробовать другой процесс вместо того, чтобы бросать 502 Bad Gatway.
Пока я не нашел возможности сделать nginx
реагирует на сбой. У кого есть идеи, как этого можно достичь? Или есть более простое решение, которое я пропустил?
connect() to unix:/run/php/php7.0-fpm.sock failed (11: Resource temporarily unavailable)
Вы не можете переместить запрос из одного процесса в другой внутри одного и того же восходящего потока, но вы можете переместить его из одного восходящего потока в другой.
Прежде всего, вам нужно как минимум два апстрима (вам понадобятся два разных php-пула):
upstream yourproject {
server unix:/run/php/php7.0-fpm_primary.sock;
server unix:/run/php/php7.0-fpm_secondary.sock;
}
Затем вы можете настроить обход отказа между ними:
location ~ \.php$ {
# First, you need to capture fastcgi errors
fastcgi_intercept_errors on;
# Specifies in which cases a request should be passed to the next server
fastcgi_next_upstream error timeout http_500 http_503;
# Limits the time during which a request can be passed
# to the next server
fastcgi_next_upstream_timeout 10s;
# Limits the number of possible tries for passing
# a request to the next server
fastcgi_next_upstream_tries 2;
fastcgi_pass yourproject;
}
Но это не решит вашу проблему, потому что вы будете делать обход отказа между одним и тем же сервером.
Я предлагаю вам:
Использовать TCP-сокеты вместо UNIX-сокетов, они более надежны и стабильны для высокого параллелизма:
вверх по течению вашего проекта {
сервер 127.0.0.1:9000;
}
Очевидно, что вы указали ваш php на этот TCP-разъем в вашей конфигурации php-пула (listen = 127.0.0.1:9000
)
Увеличьте процесс и fd ограничения /etc/limits.conf
:
* мягкий ноутбук 65536
* твёрдый ноутбук 65536
* твёрдый нпрк 65536
* мягкий nproc 65536
Увеличьте net.core.somaxconn
и net.core.netdev_max_backlog
в /etc/sysctl.conf
. Возможно, вы достигли предела.
Если вы используете pm = dynamic
в пуле конфигурации PHP, проверьте эти параметры и настройте их в соответствии с документацией и вашими системными ресурсами: pm.max_children
, pm.start_servers
, pm.min_spare_servers
, pm.max_spare_servers
. Может быть, вы тоже достигаете предела.
Увеличьте pm.max_requests
в вашей конфигурации PHP, чтобы избежать слишком частого процесса перезапуска.
Если это не сработает, скопируйте и вставьте ваши конфигурационные файлы PHP и Nginx, чтобы посмотреть на них глубже.
.