背景
我有以下 Nginx 配置,它负载平衡在 2 个不同服务器上运行的 2 个 Tomcat 服务器:
### http://nginx.org/en/docs/http/ngx_http_upstream_module.html#hash
upstream backend_w_affinity {
hash $request_uri consistent;
server 192.168.110.11:8080;
server 192.168.110.12:8080;
}
server {
listen 80 default_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location ~ ^/path/to/rest/endpoint$ { proxy_pass http://backend_w_affinity; }
}
当我使用以下curl
命令在 Nginx 驱动流量时,它似乎很好。
$ watch "curl -iI http://10.128.13.153/path/to/rest/endpoint"
HTTP/1.1 401 Unauthorized
Server: nginx/1.8.0
Date: Tue, 09 Jun 2015 01:31:13 GMT
Content-Type: application/xml;charset=ISO-8859-1
Content-Length: 231
Connection: keep-alive
注意:我意识到我得到了上面的 401。肯定有 Tomcat 启动了,如果我更改路径,使其指向 Tomcat 中的静态页面,这样我得到 200 个,它的行为仍然相同,所以目前这似乎不是问题。
最初看起来不错
运行上述curl
命令后,我的所有流量都被定向到第一个 Tomcat 服务器。如果我停止 Tomcat,那么所有流量都会故障转移到第二个 Tomcat 服务器。
我的问题
当我恢复第一台 Tomcat 服务器时,我希望所有流量现在都保留在第二台服务器上。但是,一旦我将其恢复,流量就会被引导回第一个 Tomcat 服务器。
我怎样才能获得 Nginx,将流量留在第二台服务器上,而不是将其重定向回来?
如果您希望流量即使在上游组成员资格发生变化的情况下仍坚持到服务器,则需要使用“粘性”会话。只要可用,一致的哈希就会选择相同的服务器,这似乎不是您想要的。
在您的情况下,您正在对 URI 进行哈希处理,如果您在 nginx 中使用 proxy_cache,这对“缓存位置”很有用。然而,一致的哈希意味着对于给定的 URI,一个服务器将始终是“首选”,因此一旦它重新上线,nginx 就会切换回它。
有来自 3rd 的开源 nginx 可用的粘性会话模块,或者在商业“NGINX Plus”中有一个本机粘性会话选项。
无需附加模块或商业 nginx 订阅也可以进行粘性会话,但这有点难看。您可以将 map、proxy_pass 与目标中的变量主机名和备用位置结合使用。您还需要在每个后端服务器中设置一个唯一的标头来标识它们(因此它们发送了一个“X-Loadbalace-ID”标头。这可能是会话 cookie 的一部分,例如 Tomcat JVM 路由。我们实际上仍然运行它生产中的配置,因为它早于 nginx 上粘性会话的可用性。
像这样的东西可能对你有用(我们所做的未经测试的简化):