我有一个监听 UNIX 套接字的服务器应用程序,Nginx 充当反向代理。
现在我希望 Nginx 等到我的应用程序上线,例如我部署更新并重新启动它,没有向客户端返回任何错误。
这是我的 Nginx 配置中的内容:
location / {
# proxy_pass http://localhost:8080;
proxy_pass http://unix:/tmp/MyApp.sock;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 60;
}
但是,每当我的应用程序关闭时,Nginx 就会返回
502 Bad Gateway
立即。显然,所有 proxy_*_timeout
设置都没有帮助。
本地 TCP 套接字也会发生同样的情况。使用 UNIX 套接字,当我关闭应用程序时,我确保删除套接字文件,以便 Nginx 可以看到没有应用程序在运行。
我怎样才能告诉它实际上等待一段时间直到套接字变得可用?
我不认为核心nginx有这样的功能。然而,使用 nginx-lua-module 可以实现类似的效果。即使使用该模块不适合您,我也会在这里发布工作示例,以防对其他人有所帮助。
error_page 502 = @error_502;
location / {
proxy_pass http://localhost:8080;
...
}
location = /heartbeat {
internal;
proxy_pass http://localhost:8080;
}
location @error_502 {
default_type text/plain;
rewrite_by_lua_block {
local timeout = 10
local uri = ngx.var.uri
local args = ngx.var.args
local res = { status = 0 }
while timeout > 0 do
ngx.sleep(1)
res = ngx.location.capture("/heartbeat")
if res.status == 200 then break end
timeout = timeout - 1
end
if res.status == 200 then
ngx.exec(uri, args)
end
}
content_by_lua_block {
ngx.status = ngx.HTTP_SERVICE_UNAVAILABLE
ngx.say("I'd waited too long... exiting.")
ngx.exit(ngx.OK)
}
}
或者,要返回标准的 nginx 503 页面,您可以将上面的配置更改为
...
location @error_502 {
rewrite_by_lua_block {
...
if res.status == 200 then
ngx.exec(uri, args)
else
ngx.exec("@return_503")
end
}
}
location @return_503 {
return 503;
}
ngx.sleep
是非阻塞的,其参数的粒度为微秒。您的应用程序应该能够处理 /heartbeat
路线才能使用它(可能消耗尽可能少的处理时间)。我确信这也可以适应使用 UNIX 套接字(也许您需要将上游定义移动到单独的 upstream
块)。
ngx.location.capture
来发出子请求,因此由于this限制,它与HTTP/2协议不兼容(如果需要,请阅读整个讨论以找出可能的解决方法)。
我不会称之为解决方案,但有一种方法可以通过
resolver
来实现这一点。为此,您需要一个 DNS,docker
将携带一个,但在您的情况下,您需要在您的服务器上自行设置。
server
{
resolver 127.0.0.11 valid=120s; #DNS-IP
resolver_timeout 60; # Timeout for resolver response
}
location / {
set $upstream_service URI; #URI= DNS-Name:Port
proxy_pass http://$upstream_service;
}
因此 nginx 无法检查服务的可用性并询问解析器。等待解析器答复直至超时。如果在超时时间内没有应答:502,如果服务在这段时间内返回,它将应答,nginx 将响应 200。
但我不知道它是否可以与袜子一起使用..