Re: Configuring nginx to retry a single upstream server

2021-05-25 Пенетрантность Maxim Dounin
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

2021-05-25 Пенетрантность Evgeniy Berdnikov
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

2021-05-25 Пенетрантность Gena Makhomed

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

2021-05-23 Пенетрантность Maxim Dounin
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

2021-05-22 Пенетрантность Gena Makhomed

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

2021-05-22 Пенетрантность Oleg A. Mamontov

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

2021-05-22 Пенетрантность Gena Makhomed

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

2021-05-22 Пенетрантность fox
Можете поставить 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

2021-05-22 Пенетрантность 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 этого сделать нельзя.

--
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

2021-05-21 Пенетрантность Илья Шипицин
есть несколько лайфхаков, которые упрощают жизнь, когда у вас единственный
бекенд (но ответа на ваш вопрос у меня нет)

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

2021-05-21 Пенетрантность Evgeniy Berdnikov
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

2021-05-21 Пенетрантность Gena Makhomed

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

2021-05-21 Пенетрантность Evgeniy Berdnikov
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

2021-05-20 Пенетрантность 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