Configuring nginx to retry a single upstream server

Evgeniy Berdnikov bgx на protva.ru
Пт Май 21 07:09:02 UTC 2021


On Fri, May 21, 2021 at 12:05:45AM +0300, Gena Makhomed wrote:
> Есть nginx, который проксирует запросы на единственный бекенд php-fpm.
> Во время перезапуска php-fpm клиентам сразу сыпятся 5хх ошибки.
> 
> Каким образом можно настроить nginx так, чтобы он в случае ошибки
> связи с бекендом пытался достучаться до него в течении N секунд
> (например, 30 сек), с интервалом, например, в K секунд
> (например, 0.1 сек) ?
> 
> Тогда клиент вместо сообщения про ошибку видел бы просто небольшое
> замедление ответа сервера на секунду или максимум несколько секунд,
> что гораздо лучше, чем мгновенный возврат сообщения про ошибку 5хх.

 Возврат 5xx говорит о том, что либо
 
 1. хост недоступен по сети (возможно, ребутается), по сисколу connect(2)
    возвращается EHOSTUNREACH.
 2. хост доступен, но порт в этот момент не прослушивается, тогда
    возвращается ECONNREFUSED,
 3. приложение возвращает 5xx и nginx форвардит этот ответ клиенту.

 Ели речь о п.2 и п.3 (перезапуск php-fpm), то это вовсе не ситуация
 "нет связи с бэкендом", которая п.1.

 Если же речь о ребуте хоста php-fpm, то либо бэкенд в локальной сети и
 оказывается недоступен по arp-у, тогда EHOSTUNREACH возвращается после
 arp-овского таймаута (обычно это 3 секунды), если бэкенд в другой
 подсети, то обычно шлюз возвращает icmp[host-unreachable] по той же
 причине, через те же 2-3 секунды.

> Может быть как-то с помощью njs или nginx-module-perl или с помощью
> ngx_http_upstream_module это можно сделать? Или тут единственно возможный
> вариант - писать патч на С для решения этой задачи?

 Ох... да просто отрубить пакетным фильтром (файрволом) этот бэкенд
 на время всех манипуляций по перезапуску php-fpm. А когда запустится,
 открыть обратно. Конечно, proxy_connect_timeout подкрутить.
 И заскриптовать всё.
-- 
 Eugene Berdnikov


Подробная информация о списке рассылки nginx-ru