Re: Configuring nginx to retry a single upstream server
Hello! On Tue, May 25, 2021 at 12:15:54PM +0300, Gena Makhomed wrote: > On 24.05.2021 6:05, Maxim Dounin wrote: > > >>> Можете поставить haproxy - он как раз будет держать клиента секунд 10, > >>> пока бекэнды перезагружаются. Браузеру придётся ждать эти 10 секунд, > >>> но зато он не получит 5хх ошибку. > >> > >> Могу поставить haproxy, но haproxy - это не веб-сервер, он не умеет > >> отдавать статику. Значит надо будет использовать одновременно и haproxy > >> и nginx - а это будет примерно в два раза больше работы. Хотелось бы > >> этой лишней работы избежать и обойтись одним только nginx. > >> > >> To: Maxim Dounin: Как я понял, сейчас nginx этого не умеет. > >> Планируется ли в будущем добавить такую функциональность в nginx? > > > > Если это зачем-то надо - то это можно сделать с помощью > > конфигурации, error_page + delay + повторное обращение к тому же > > бэкенду. > > Каким образом можно сделать delay обработки запроса в nginx? Есть более одного способа, из штатного - задержки умеют делать limit_req (но время контролируется плохо), perl и njs. Из нештатного - лет десять назад я сделал простой модуль для этого, и с тех пор пользуюсь регулярно: http://mdounin.ru/hg/ngx_http_delay_module/ Возможно затащим в базу. [...] > Есть ли шансы, что директива queue появится в open source версии nginx? Я бы на это не рассчитывал. -- Maxim Dounin http://mdounin.ru/ ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
On Tue, May 25, 2021 at 12:15:54PM +0300, Gena Makhomed wrote: > >Но вообще если перезапуск php-бэкенда под боевой нагрузкой > >считается нормальным рабочим действием, то браузер так или иначе > >имеет шанс получить неполный ответ же. Пытаться в подобной > >ситуации ещё и ошибки обрабатывать - как по мне, выглядит > >излишним. > > Это не обязательно может быть перезапуск php-бэкенда > под боевой нагрузкой, может быть и просто временная > деградация сети между nginx-фронтендом и бэкендом. Временная деградация сети приводит к ретрансмиссиям пакетов, это делается ядром ОС и процесс неуправляем со стороны пользователя, за исключением общего таймаута. А если таймаут не достигнут, то 500-х ошибок от деградации сети не может быть. К тому же изначально речь шла о unix-сокетах, там совершенно иные правила игры. -- Eugene Berdnikov ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
On 24.05.2021 6:05, Maxim Dounin wrote: Можете поставить haproxy - он как раз будет держать клиента секунд 10, пока бекэнды перезагружаются. Браузеру придётся ждать эти 10 секунд, но зато он не получит 5хх ошибку. Могу поставить haproxy, но haproxy - это не веб-сервер, он не умеет отдавать статику. Значит надо будет использовать одновременно и haproxy и nginx - а это будет примерно в два раза больше работы. Хотелось бы этой лишней работы избежать и обойтись одним только nginx. To: Maxim Dounin: Как я понял, сейчас nginx этого не умеет. Планируется ли в будущем добавить такую функциональность в nginx? Если это зачем-то надо - то это можно сделать с помощью конфигурации, error_page + delay + повторное обращение к тому же бэкенду. Каким образом можно сделать delay обработки запроса в nginx? И если надо будет сделать timeout в 10 секунд с интервалом между попытками обращения к бэкенду в 1 секунду - это надо будет описать 10 различных locations в конфигурации nginx? Но вообще если перезапуск php-бэкенда под боевой нагрузкой считается нормальным рабочим действием, то браузер так или иначе имеет шанс получить неполный ответ же. Пытаться в подобной ситуации ещё и ошибки обрабатывать - как по мне, выглядит излишним. Это не обязательно может быть перезапуск php-бэкенда под боевой нагрузкой, может быть и просто временная деградация сети между nginx-фронтендом и бэкендом. Есть ли шансы, что директива queue появится в open source версии nginx? -- Best regards, Gena ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
Hello! On Sat, May 22, 2021 at 03:49:01PM +0300, Gena Makhomed wrote: > On 22.05.2021 15:31, fox wrote: > > > Можете поставить haproxy - он как раз будет держать клиента секунд 10, > > пока бекэнды перезагружаются. Браузеру придётся ждать эти 10 секунд, > > но зато он не получит 5хх ошибку. > > Могу поставить haproxy, но haproxy - это не веб-сервер, он не умеет > отдавать статику. Значит надо будет использовать одновременно и haproxy > и nginx - а это будет примерно в два раза больше работы. Хотелось бы > этой лишней работы избежать и обойтись одним только nginx. > > To: Maxim Dounin: Как я понял, сейчас nginx этого не умеет. > Планируется ли в будущем добавить такую функциональность в nginx? Если это зачем-то надо - то это можно сделать с помощью конфигурации, error_page + delay + повторное обращение к тому же бэкенду. Но вообще если перезапуск php-бэкенда под боевой нагрузкой считается нормальным рабочим действием, то браузер так или иначе имеет шанс получить неполный ответ же. Пытаться в подобной ситуации ещё и ошибки обрабатывать - как по мне, выглядит излишним. -- Maxim Dounin http://mdounin.ru/ ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
On 22.05.2021 18:22, Oleg A. Mamontov wrote: Функциональность, позволяющая реализовать подобную логику, имеется в коммерческой версии: http://nginx.org/ru/docs/http/ngx_http_upstream_module.html#queue Хостинг сайтов на PHP - это не тот бизнес, который даст возможность купить коммерческую версию nginx, мы столько денег не зарабатываем. Когда-то параметр max_conns=number директивы server был частью только коммерческой подписки, а потом он стал доступен и в open source версии. Может быть имеет смысл продолжить эту добрую традицию, может быть имеет смысл и директиву queue сделать доступной в open source версии nginx? -- Best regards, Gena ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
On Sat, May 22, 2021 at 03:49:01PM +0300, Gena Makhomed wrote: On 22.05.2021 15:31, fox wrote: Можете поставить haproxy - он как раз будет держать клиента секунд 10, пока бекэнды перезагружаются. Браузеру придётся ждать эти 10 секунд, но зато он не получит 5хх ошибку. Могу поставить haproxy, но haproxy - это не веб-сервер, он не умеет отдавать статику. Значит надо будет использовать одновременно и haproxy и nginx - а это будет примерно в два раза больше работы. Хотелось бы этой лишней работы избежать и обойтись одним только nginx. To: Maxim Dounin: Как я понял, сейчас nginx этого не умеет. Планируется ли в будущем добавить такую функциональность в nginx? Функциональность, позволяющая реализовать подобную логику, имеется в коммерческой версии: http://nginx.org/ru/docs/http/ngx_http_upstream_module.html#queue -- Best regards, Gena ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru -- Cheers, Oleg A. Mamontov ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
On 22.05.2021 15:31, fox wrote: Можете поставить haproxy - он как раз будет держать клиента секунд 10, пока бекэнды перезагружаются. Браузеру придётся ждать эти 10 секунд, но зато он не получит 5хх ошибку. Могу поставить haproxy, но haproxy - это не веб-сервер, он не умеет отдавать статику. Значит надо будет использовать одновременно и haproxy и nginx - а это будет примерно в два раза больше работы. Хотелось бы этой лишней работы избежать и обойтись одним только nginx. To: Maxim Dounin: Как я понял, сейчас nginx этого не умеет. Планируется ли в будущем добавить такую функциональность в nginx? -- Best regards, Gena ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
Можете поставить haproxy - он как раз будет держать клиента секунд 10, пока бекэнды перезагружаются. Браузеру придётся ждать эти 10 секунд, но зато он не получит 5хх ошибку. 22.05.2021 19:26, Gena Makhomed пишет: On 21.05.2021 11:20, Evgeniy Berdnikov wrote: nginx и php-fpm у меня находятся на одном и том же хосте, связь между ними идет через unix domain socket по протоколу fastcgi. ... Речь идет о перезапуске php-fpm командой "systemctl restart php-fpm" Если делать "systemctl reload php-fpm" - это не всегра срабатывает, иногда после релоада php-fpm оказывается в нерабочем состоянии, поэтому использую именно "systemctl restart php-fpm" для изменения конфигурации php-fpm, тогда и случаются 502 ошибки с сайтами. В таком случае, может быть, сконфигурить 2 бэкенда, отличающиеся лишь сокетами (и какими-нибудь pid-файлами), описать их в одном upstream{} и не перезапускать php-fpm, а поднимать 2й и гасить 1й? Да, так работает. Но поднимать на сервере два бэкенда - это - в два раза больше работы. Поэтому очень хочется этой лишней работы избежать и обойтись одним бэкендом. Но скорее всего, средствами nginx этого сделать нельзя. ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
On 21.05.2021 11:20, Evgeniy Berdnikov wrote: nginx и php-fpm у меня находятся на одном и том же хосте, связь между ними идет через unix domain socket по протоколу fastcgi. ... Речь идет о перезапуске php-fpm командой "systemctl restart php-fpm" Если делать "systemctl reload php-fpm" - это не всегра срабатывает, иногда после релоада php-fpm оказывается в нерабочем состоянии, поэтому использую именно "systemctl restart php-fpm" для изменения конфигурации php-fpm, тогда и случаются 502 ошибки с сайтами. В таком случае, может быть, сконфигурить 2 бэкенда, отличающиеся лишь сокетами (и какими-нибудь pid-файлами), описать их в одном upstream{} и не перезапускать php-fpm, а поднимать 2й и гасить 1й? Да, так работает. Но поднимать на сервере два бэкенда - это - в два раза больше работы. Поэтому очень хочется этой лишней работы избежать и обойтись одним бэкендом. Но скорее всего, средствами nginx этого сделать нельзя. -- Best regards, Gena ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
есть несколько лайфхаков, которые упрощают жизнь, когда у вас единственный бекенд (но ответа на ваш вопрос у меня нет) 1) можно, и пожалуй, нужно указывать max_fails=0 (чтобы не держать бекенд в грейлисте, а максимально пытаться отправлять на него запросы) 2) можно продублировать бекенд несколько раз, как будто у вас несколько серверов, это позволяет улучшить ситуацию, когда деградировала сеть между балансером и бекендом, тогда timeout while connecting будет переотправлен на якобы следующий бекенд пт, 21 мая 2021 г. в 02:05, Gena Makhomed : > Здравствуйте, All! > > Есть nginx, который проксирует запросы на единственный бекенд php-fpm. > Во время перезапуска php-fpm клиентам сразу сыпятся 5хх ошибки. > > Каким образом можно настроить nginx так, чтобы он в случае ошибки > связи с бекендом пытался достучаться до него в течении N секунд > (например, 30 сек), с интервалом, например, в K секунд > (например, 0.1 сек) ? > > Тогда клиент вместо сообщения про ошибку видел бы просто небольшое > замедление ответа сервера на секунду или максимум несколько секунд, > что гораздо лучше, чем мгновенный возврат сообщения про ошибку 5хх. > > Может быть как-то с помощью njs или nginx-module-perl или с помощью > ngx_http_upstream_module это можно сделать? Или тут единственно > возможный вариант - писать патч на С для решения этой задачи? > > -- > Best regards, > Gena > > ___ > nginx-ru mailing list > nginx-ru@nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-ru ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
On Fri, May 21, 2021 at 11:03:47AM +0300, Gena Makhomed wrote: > nginx и php-fpm у меня находятся на одном и том же хосте, > связь между ними идет через unix domain socket по протоколу fastcgi. ... > Речь идет о перезапуске php-fpm командой "systemctl restart php-fpm" > Если делать "systemctl reload php-fpm" - это не всегра срабатывает, > иногда после релоада php-fpm оказывается в нерабочем состоянии, > поэтому использую именно "systemctl restart php-fpm" для изменения > конфигурации php-fpm, тогда и случаются 502 ошибки с сайтами. В таком случае, может быть, сконфигурить 2 бэкенда, отличающиеся лишь сокетами (и какими-нибудь pid-файлами), описать их в одном upstream{} и не перезапускать php-fpm, а поднимать 2й и гасить 1й? -- Eugene Berdnikov ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
On 21.05.2021 10:09, Evgeniy Berdnikov 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. nginx и php-fpm у меня находятся на одном и том же хосте, связь между ними идет через unix domain socket по протоколу fastcgi. Обрабатывать таким образом, через повтор запроса имеет смысл, разумеется, только 502 и 504 статусы на стороне nginx. Если же бекенд вернул 500 ошибку - это внутренняя ошибка бекенда, повтор тут ничем не поможет, эту ошибку надо сразу вернуть клиенту. Возврат 502 бывает в случае такой записи в логах: connect() to unix:/run/php-fpm/www.sock failed (2: No such file or directory) while connecting to upstream Сокет /run/php-fpm/www.sock отсутствует во время перезапуска php-fpm. Если же речь о ребуте хоста php-fpm, то либо бэкенд в локальной сети и оказывается недоступен по arp-у, тогда EHOSTUNREACH возвращается после arp-овского таймаута (обычно это 3 секунды), если бэкенд в другой подсети, то обычно шлюз возвращает icmp[host-unreachable] по той же причине, через те же 2-3 секунды. Речь идет о перезапуске php-fpm командой "systemctl restart php-fpm" Если делать "systemctl reload php-fpm" - это не всегра срабатывает, иногда после релоада php-fpm оказывается в нерабочем состоянии, поэтому использую именно "systemctl restart php-fpm" для изменения конфигурации php-fpm, тогда и случаются 502 ошибки с сайтами. Кроме того, иногда, время от времени, бывает еще такая ошибка: upstream timed out (110: Connection timed out) while reading response header from upstream - тогда клиенту возвращается 504 статус. Причину этих таймаутов найти не могу, поэтому и хотелось бы сделать workaround средствами nginx. Может быть как-то с помощью njs или nginx-module-perl или с помощью ngx_http_upstream_module это можно сделать? Или тут единственно возможный вариант - писать патч на С для решения этой задачи? Ох... да просто отрубить пакетным фильтром (файрволом) этот бэкенд на время всех манипуляций по перезапуску php-fpm. А когда запустится, открыть обратно. Конечно, proxy_connect_timeout подкрутить. И заскриптовать всё. Там unix domain socket, какой пакетный фильтр может быть? Кроме того, чем поможет отрубать этот бекенд, ведь он единственный? (см. тему: Re: Configuring nginx to retry a single upstream server) Будет точно так же 502 ошибка. А ведь именно этого я и хочу избежать. P.S. Понятное дело, что в случае ддос-атаки это даст amplification, но ддос-атаки можно легко детектировать, например, по количеству запросов в минуту, и если превышен какой-то предел - отключать эту функциональность с повторами запросов и возвращаться к старому поведению, так как это есть сейчас. -- Best regards, Gena ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Re: Configuring nginx to retry a single upstream server
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 mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru
Configuring nginx to retry a single upstream server
Здравствуйте, All! Есть nginx, который проксирует запросы на единственный бекенд php-fpm. Во время перезапуска php-fpm клиентам сразу сыпятся 5хх ошибки. Каким образом можно настроить nginx так, чтобы он в случае ошибки связи с бекендом пытался достучаться до него в течении N секунд (например, 30 сек), с интервалом, например, в K секунд (например, 0.1 сек) ? Тогда клиент вместо сообщения про ошибку видел бы просто небольшое замедление ответа сервера на секунду или максимум несколько секунд, что гораздо лучше, чем мгновенный возврат сообщения про ошибку 5хх. Может быть как-то с помощью njs или nginx-module-perl или с помощью ngx_http_upstream_module это можно сделать? Или тут единственно возможный вариант - писать патч на С для решения этой задачи? -- Best regards, Gena ___ nginx-ru mailing list nginx-ru@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-ru