Nginx – can nginx retry request if unicorn is overloaded and returns a 502

nginxunicorn

Is it possible to have nginx retry a second backend before returning a 502 to the client?

Would something like this work?

Front end:

# haproxy:85 => [a few app servers]:8000
# more specifically:
# haproxy => [nginx => unicorn (502 when busy)]

# Will this try a second app server when the first returns 502?

upstream haproxy {
  server 127.0.0.1:85;
  server 127.0.0.1:85 backup;
}

server {
  listen 80;
  proxy_pass http://haproxy;
  proxy_next_upstream http_502;
}

Back end:

upstream unicorn {
  server unix:/tmp/unicorn.sock fail_timeout=0;
}

server {
  listen 8000;
  proxy_pass http://unicorn;
}

Anyway, I'm just curious. This is actually probably pretty stupid because the retry could end up hitting the same overloaded server and would end up returning a 502 anyway…

Best Answer

As far as I know, Nginx automatically tries every available server - and if all return an error, it will return the error code of the last response.

proxy_next_upstream just seems to offer some finer control as to what errors will be processed and which will be ignored (but the default is already any 'error' in connecting, sending, or receiving - with, I believe, a 60s timeout).

As per the documentation (the wording could use some work):

"If with an attempt at the work with the server error occurred, then the request will be transmitted to the following server and then until all workers of server not are tested. If successful answer is not succeeded in obtaining from all servers, then to client will be returned the result of work with the last server."

You could verify this behaviour with a script that logs the time (or any data) to a file and returns 502. If you find only 1 line logged, then nginx didn't try multiple servers, if you find two lines logged, it did.