Nginx之自动重试机制
1. 问题现象
结构:nginx+tomcat(4台),nginx已安装主动监测模块upstream_check_module
问题:当一台tomcat已经down,但是另外4台应用不可用(即IP和端口都是可用的,但是业务是不可用的,因为代码出错),正常来说:反馈给客户端应该是404错误,但是反馈客户端的却是502.
分析:经常查询nginx日志,发现当请求是POST请求,响应的是404。当请求是GET,HEAD请求时,响应的是502。
域名 175.6.201.129 order [28/Sep/2022:16:19:18 +0800] "GET /order/testConfig HTTP/1.1" 502 626
并且upstream_addr变成了:IP upstream_name
经过查询nginx官网,发现是因为nginx的自动重试机制导致这个问题。
2. 自动重试机制
Nginx通过反向代理做负载均衡时,如果被代理的其中一个服务发生错误或者超时的时候,通常希望Nginx自动重试其他的服务,从而实现服务的高可用性。实际上Nginx本身默认会有错误重试机制,并且可以通过proxy_next_upstream来自定义配置。
在Nginx配置文件中,proxy_next_upstream用于指定在什么情况下Nginx会将请求转移到其他服务器上。其默认值是proxy_next_upstream error timeout,即发生网络错误以及超时,才会重试其他服务器。默认情况下服务返回500状态码是不会重试的。
1. 指令proxy_next_upstream
1. 使用方法
| Syntax: | proxy_next_upstream |
|---|---|
| Default: |
proxy_next_upstream error timeout; |
| Context: | http, server, location |
location ^~ /order/ {
add_header Access-Control-Allow-Origin *;
proxy_pass http://order;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_redirect off;
client_max_body_size 50m;
client_body_buffer_size 256k;
proxy_connect_timeout 120;
proxy_send_timeout 120;
proxy_read_timeout 60;
proxy_buffer_size 256k;
proxy_buffers 4 256k;
proxy_max_temp_file_size 128m;
proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
}
2. non_idempotent
通常情况下,如果请求使用非等幂方法(POST、LOCK、PATCH),请求失败后不会再到其他服务器进行重试。加上non_idempotent选项后,即使是非幂等请求类型(例如POST请求),发生错误后也会重试。
生产环境不建议开启non_idempotent
3. 什么是幂等方法
如果使用该方法的多个相同请求对服务器的预期效果与单个请求的效果相同,则认为请求方法是幂等的。常见的HTTP请求方法中,GET是幂等的,而POST是非幂等的。
3. 解决方法
1. 关闭nginx重试机制,proxy_next_upstream off
2. 重试机制去掉http_404
3. 增加模块动态更新upstream,把down掉的那台机器去掉,就不会出现这种现象

浙公网安备 33010602011771号