最近线上用户请求时不时返回502,并且没多大规律,我们的部署架构是Nginx + web应用,nginx中的upstream配置了两个web做负载均衡。
经过分析web应用,出现502的时候请求并没有到达web应用,所以可以断定请求502是Nginx直接返回,查看Nginx的access.log可以查到对应的请求信息,确实返回502
GET /api/app/1 HTTP/1.1" 502 541 17.340
Nginx 的error.log日志相关异常:
upstream server temporarily disabled while reading response header from upstream, client..
no live upstreams while connecting to upstream, client..
可以看到,是因为upstream server无效了,没有可用的web应用导致,看到这个异常时,第一个反应是难不成两台web会都挂了???
但是查看web的运行日志和服务状态service xx status,当出现502时,web应用的运行都是正常的,并没有重启或是宕机,所以排除web应用问题,那会不会是之前有其他异常导致这个502!?继续分析了出现502之前的日志,果然,在502之前都有一个500异常,并且这个异常很有频率的出现。
"GET /api/project HTTP/1.1" 500 214 0.087 "http://xx.com/" "Mozilla/5.0 (Win
dows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" "-" "-" xxx.net "10.x.x.x:8081, 10.x.x.x:8081" "500, 500" "0.045, 0.042"
通过url分析发现,这个是因为页面有一个定时任务,会十秒刷新一次,而这个api正好因为有bug,请求会返回500,不过有点想不通的是500为什么会导致后续正常请求出现502,后来通过分析nginx的nginx.conf,原来nginx配置了proxy_next_upstream属性,这个属性作用是如果发现请求返回的是后面的配置状态时就会转发到下一个upstream,例如:500
location / {
proxy_pass http://app-proxy;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 3;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_pass_request_headers on;
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;
set $domain default;
结果测试发现,如果每个实例都返回500后,接下来的请求就会出现502,如果访问正常的api,又会恢复正常,说明nginx当发现upstream都为500的时候,就会临时disable所有upstream,也就是上面error.log上出现的“upstream server temporarily disabled”,后续请求就会有“no live upstreams”问题,但是出现502后,新请求会重新检测,当请求是200,就会恢复正常。
解决:问题原因找到了,解决办法也就简单了,这个500一般是服务器端的bug,一般请求都不会直接返回500,出现问题及时解决就好,另外这个使用这个属性时得注意,如果请求是后面枚举的状态时,nginx会直接转到另外一个upstream,所以会出现多个实例都接收到请求的情况,有些情况下是不允许的,所以使用的时候需要分析一下。