记一次生产环境Nginx间歇性502的事故分析过程

最近我们我们在将部分业务从自有机房迁移到国内某云服务器上,在小规模上量后,发现Nginx间接性出现大量502。异常出现的特点是,一瞬间后端多个独立部署的服务全部出现502。

我们的服务架构如下:

+--------+  HTTP   +-------+  HTTP   +-------+
| Client | ------> |       | ------> | API A |
+--------+         |       |         +-------+
                   |       |  HTTP   +-------+
                   | Nginx | ------> | API B |
                   |       |         +-------+
                   |       |  HTTP   +-------+
                   |       | ------> | API C |
                   +-------+         +-------+

一般讲,Nginx 502就是后端处理不过来,但查看监控后端几个API的负载均很低,当前请求的QPS远远低于服务的上限。而且同一瞬间,多套独立部署的API均处理不过来的概率也比较低。

我们简单做了个对比测试,分别对域名(请求走Nginx)与直接通过IP对内网一个API通过wrk进行小规模压测。


压测截图
压测截图

对比测试发现,直接通过域名走Nginx对API进行压测的话,QPS远远小于预期,并且存在大量失败请求。基本断定问题出在Nginx —> API 这条链路上。同时排除了后端服务响应不过来的可能性。网络问题可能性大一点。

一开始我们怀疑云服务商对内网带宽做了限制,我们观察内网带宽达到在200MB/S后就上不去了,所以我们在Nginx机器上ping后端服务,观察一段时间发现有小量抖动,但基本延迟正常。那云服务商对网络做限制的可能性就变小了很多。

我们观察Nginx错误日志:

2017/09/26 14:23:00 [error] 4950#4950: *4162133210 no live upstreams while connecting to upstream, client: xxx.xxx.xxx.xxx, server: api.xx.xxxxxxx.cn, request: "POST /xx/xxxxxx/bidder HTTP/1.1", upstream: "http://xxxxxxxxxx/bidder", host: "api.xx.xxxxxxx.cn"

这里出现no live upstreams while connecting to upstream, 也就说一瞬间Nginx检测不到任何存活的后端服务,而网络又没有大波动,那就可能是TCP链接出问题。打开Zabbix监控发现TCP连接数的确发生剧烈的波动现象。

异常TCP连接数趋势
异常TCP连接数趋势

这时候问题很明显,Nginx->API这一链路存在大量的TCP链接被回收的情况,我们马上在API机器上查看链接状态

shell > netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
SYN_RECV     1
ESTABLISHED      656
FIN_WAIT1    4
TIME_WAIT    153429

TIME_WAIT特别的多,大量的连接被API侧主动关闭了。这说明Nginx->API这一步请求并没有Keep-Alive,我们检查Nginx,确定是配置了Keep-Alive

upstream xxxxxxx {
    server 172.17.192.98:8087 max_fails=3 fail_timeout=5s weight=1;
    server 172.17.192.99:8087 max_fails=3 fail_timeout=5s weight=1;
    keepalive 256;
}

因为业务的特殊性,我们很确定Client一定为携带Keep-Alive的。那么说明后端API没正确的支持Keep-Alive,我们开始对API代码逻辑进行Review,但我们检查配置,发现服务默认是开启Keep-Alive的,我们进行显式的配置,仍然不起作用。这里存在一个可能性就是我们时候的Web框架有BUG。所以我们接下来做了一个测试,来验证服务是否开启了Keep-Alive。

Keep-Alive测试
Keep-Alive测试

我们使用curl连发两次请求,在第二次请求的报文中,我们可以看到Re-using existing connection。这说明连接被复用,后端API服务对Keep-Alive的支持是正常的。

这时候就陷入了困境了,求助Google大神后,发现Nginx支持Keep-Alive还需要在配置转发的时候的时候增加以下配置:

location ^~ /xxxxx/ {
    ...
    proxy_set_header Connection "Keep-Alive";
    ...
}

贴上配置后,惊奇的发现问题解决了,后端服务器TIME_WAIT的链接下降到2位数,并且也不再出现502现象。棒!

后续发展

在HTTP 1.0中,Keep-Alive默认是关闭的,需要在请求头显式加上Connection: Keep-Alive,才能启用Keep-Alive。但在HTTP 1.1中,该功能默认是开启的,需要使用Connection: Close才会禁用Keep-Alive。目前大部分浏览器都是使用HTTP 1.1协议。

我们后来分析所有的Client请求,发现全部都是1.1协议,这就很诡异了。接下来我们在Nginx->API这条链路上捉包,惊奇的发现,竟然出现部分流量是1.0协议的,部分是1.1协议的。这里就解释了为什么会出现连接无法复用的问题。所以我们统一将所有的转发配置都增加了以下规制强制指定使用1.1协议。

location ^~ /xxxxxx/ {
    ...
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    ...
}

但整个事故中,仍然存在几个疑点:

  1. 为什么Nginx转发的流量中,会混入1.0协议的请求呢?
  2. 是什么原因导致Nginx或Nginx所在服务器的操作系统在对TCP链接大量回收,并且把正常连接也回收掉导致后端Server "no live upstreams"了呢?

目前暂无头绪,后续分析有结果再补上。

原文地址: http://xiezefan.me/2017/09/27/nginx-502-bug-trace/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,738评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,377评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,774评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,032评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,015评论 5 361
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,239评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,724评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,374评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,410评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,457评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,132评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,733评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,804评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,022评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,515评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,116评论 2 341

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,566评论 18 139
  • 第一章 Nginx简介 Nginx是什么 没有听过Nginx?那么一定听过它的“同行”Apache吧!Ngi...
    JokerW阅读 32,628评论 24 1,002
  • 1. Nginx的模块与工作原理 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单...
    rosekissyou阅读 10,178评论 5 124
  • O:人际沟通技巧一、八把手术刀批评D:实事求是,就事论事无法更改,不要去说批评I:公开挑错,一定避免赞美之后,再挑...
    邓男神Sweety阅读 1,011评论 0 0
  • 这是我们认识的第三年了吧?也许多于第三年了。可是我觉得一年一年过去我好想愈发的不认识你。虽然总是一遍遍的发现我还是...
    Stupid_Sakuragi阅读 288评论 0 0