Nginx upstream 失效转移机制研究
结论
经过多次模拟线上的环境测试,Nginx 负载均衡技术默认情况下已经对于 connect refused
(状态码表现为 502
)和 time out
(状态码表现为 504
)做了失效转移,使用的是 upstream
模块的 proxy_next_upstream
指令(这个选项默认是启动的)来实现。
对于 http GET
请求,当这个请求转发到上游服务器发生断路,或者读取响应超时则会将同样的请求转发到其他上游服务器来处理,如果所有服务器都超时或者断路,则会返回 502
或者 504
错误。
对于http POST
请求,当这个请求转发到上游服务器发生断路,则会将请求转发到其他上游服务器来处理,但是如果这个请求发生了读取超时,则不会做失效转移,会返回 504
错误,Nginx 之所以这么做应该是为了防止同一个请求发送两次,比如涉及到银行的充值等操作就会发生很严重的 bug。以下是模拟线上的场景测试得出的结论:
- 上游服务器有两台,一台处于 down 状态,另一台处于正常服务状态,那么来自客户端的
GET
和POST
请求都会通过 Nginx 的失效转移机制路由到正常状态的机器,返回200
状态码,并不会返回给客户端502
错误; - 上游服务器有两台,两台都 down 了,那么会不管是
GET
还是POST
请求都会直接返回给客户端502
错误; - 上游服务器有两台,一台机器的
http GET
和POST
接口都正常 return,另一台相同的接口死循环,模拟超时。
这种情况下如果客户端的请求路由到了正常机器,那么直接返回200
。
如果请求路由到了死循环的接口,并且是GET
请求,那么会等待 Nginx 设置的超时时间过后,然后将请求转发到另一台机器的正常接口。
如果请求路由到了死循环的接口,并且是POST
请求,那么等待 nginx 设置的超时时间过后直接返回504
,没有进行失效转移,防止请求的重复发送; - 上游服务器有两台,两台机器的
http GET
和POST
接口都死循环,模拟超时,那么对于GET
请求会进行请求转发到另一台尝试,对于POST
请求直接返回504
,不会进行进一步尝试;
论证环境及工具
- 一台前端 Nginx 服务器;
- 两台上游服务器;
- Nginx 配置: