如果后端宕机,则短暂缓冲对 nginx 的请求

如果后端宕机,则短暂缓冲对 nginx 的请求

我有一个 nodejs 应用程序永远在 nginx 后面运行。当我部署新代码时,我就会这样做,forever restart但即使在这么短的时间内,我也无法承受 502 错误。

如何配置 nginx 以在出现 502 时继续在此上游服务器上重试?我尝试将和设置为 eg,proxy_connect_timeout但无论如何我都会立即得到 502 :(proxy_read_timeoutproxy_send_timeout30s

我的站点配置是:

upstream my_server {
  server 127.0.0.1:3000 fail_timeout=0;
  keepalive 1024;
}

server {
 listen 3333;

server_name myservername.com;
access_log /var/log/nginx/my_server.log;

location / {
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_set_header X-NginX-Proxy true;

  # retry upstream on 502 error
  proxy_connect_timeout      30s;
  proxy_send_timeout         30s;
  proxy_read_timeout         30s;

  proxy_pass http://my_server;
  proxy_http_version 1.1;
  proxy_set_header Connection "";
  proxy_redirect off;
 }
}

当上游不可用时,是否可以在这么短的时间内缓冲请求?

答案1

这最终听起来像是你的后端的问题:nginx 向你的后端发出请求,连接立即被拒绝,因此,nginx 没有其他选择,只能将错误下游传递给用户,因为没有指定其他上游,并且timeout你指定的值在这里不起作用,因为 nginx 根本不需要等待任何事情。


我现在不知道它forever是什么或者它是如何工作的,但我想到了几个可能的解决方案。

上游发生的情况有两种可能性:

  • “永远”可能是接受连接,并立即返回错误。在这种情况下,听起来你真正应该问的是如何让它不错误处理连接,而是等到你的应用程序部署完成后,再处理请求。 opengrok服务器上的应用程序存在tomcat这个问题。

  • 没有人是聆听在您的应用程序应该运行的端口上,因此,内核会立即丢弃数据包,并立即返回 TCP RST 数据包。

    • 如果TCP RST是原因,您可以通过forever保留监听套接字或配置内核来将传入的数据包排队一段时间来解决它,以便有人稍后接收它们,这样当forever重新启动时,它将有一个完整的队列准备好提供服务。

    • 配置内核TCP RST在无人监听时不发出请求,这样timeoutnginx 中的配置就会生效。随后,配置nginx向另一个上游发出第二个请求。

如果您解决了上述任一种情况,那么您就完成了。

否则,您必须尝试配置 nginx 来修复该问题:

  • 你可以尝试proxy_cacheproxy_cache_use_stale

  • 您可以尝试使用错误处理程序:参见proxy_intercept_errors(可能仅适用于您收到的 503 是从后端传递过来的情况)并且error_page。您可能希望在错误处理程序中浪费时间,直到您的应用程序重新启动,然后再向您的应用程序发出请求。

    • 你可能会浪费时间运行第二个应用程序,它只会做sleep()无论你的应用需要多长时间才能重新部署,然后提供 HTTP 重定向,或者不响应就退出;哎呀,你可以简单地通过尝试代理到 TCP 端口来实现这一点,block drop在防火墙中,这将激活 nginx 中的超时。随后,配置 nginx 以发出第二个请求。

如果您实施上述涉及激活的方法之一timeout,则随后需要向后端发出额外请求。您可以使用upstream指令,您可以多次指定同一个服务器,或者,如果不接受,可以通过防火墙镜像端口,或者更好的是,您可以首先运行多个独立的应用服务器。

这又把我们带回到您的应用服务器:如果它无法处理干净重新部署的问题,那么也许您应该运行两个这样的应用服务器,并使用 nginx 在它们之间进行负载平衡。或者重新部署它们,然后在实际准备就绪后将 nginx 切换到新副本。否则,您怎么可能确定您的客户愿意等待 30 秒让您的 API 做出响应?

相关内容