Сказать nginx использовать другой процесс PHP для случайного «502 Bad Gateway»

На веб-сервере, который обычно довольно хорошо работает с 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)
0
задан 19 January 2018 в 10:14
1 ответ

Вы не можете переместить запрос из одного процесса в другой внутри одного и того же восходящего потока, но вы можете переместить его из одного восходящего потока в другой.

Прежде всего, вам нужно как минимум два апстрима (вам понадобятся два разных 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;
}

Но это не решит вашу проблему, потому что вы будете делать обход отказа между одним и тем же сервером.

Я предлагаю вам:

  1. Использовать TCP-сокеты вместо UNIX-сокетов, они более надежны и стабильны для высокого параллелизма:

    вверх по течению вашего проекта {
     сервер 127.0.0.1:9000;
    }
    

    Очевидно, что вы указали ваш php на этот TCP-разъем в вашей конфигурации php-пула (listen = 127.0.0.1:9000)

  2. Увеличьте процесс и fd ограничения /etc/limits.conf:

    * мягкий ноутбук 65536
    * твёрдый ноутбук 65536
    * твёрдый нпрк 65536
    * мягкий nproc 65536
    
  3. Увеличьте net.core.somaxconn и net.core.netdev_max_backlog в /etc/sysctl.conf. Возможно, вы достигли предела.

  4. Если вы используете pm = dynamic в пуле конфигурации PHP, проверьте эти параметры и настройте их в соответствии с документацией и вашими системными ресурсами: pm.max_children, pm.start_servers, pm.min_spare_servers, pm.max_spare_servers. Может быть, вы тоже достигаете предела.

  5. Увеличьте pm.max_requests в вашей конфигурации PHP, чтобы избежать слишком частого процесса перезапуска.

Если это не сработает, скопируйте и вставьте ваши конфигурационные файлы PHP и Nginx, чтобы посмотреть на них глубже.

.
1
ответ дан 4 December 2019 в 16:02

Теги

Похожие вопросы