解Bug之路——Nginx 502 Bad Gateway

转载:

前言事实证明,读过Linux内核源码确实有很大的好处,尤其在处理问题的时刻。 当你看到报错的那一瞬间,就能把现象/原因/以及解决方案一股脑的在脑中闪现。 甚至一些边边角角的现象都能很快的反应过来是为何。 笔者读过一些Linux TCP协议栈的源码,就在解决下面这个问题的时候有一种非常流畅的感觉。

Bug现场首先,这个问题其实并不难解决,但是这个问题引发的现象倒是挺有意思。 先描述一下现象吧,笔者要对自研的dubbo协议隧道网关进行压测(这个网关的设计也挺有意思,准备放到后面的博客里面)。 先看下压测的拓扑吧:

为了压测笔者gateway的单机性能,两端仅仅各保留一台网关,即gateway1和gateway2。 压到一定程度就开始报错,导致压测停止。 很自然的就想到,网关扛不住了。

网关的情况去Gateway2的机器上看了一下,没有任何报错。 而Gateway1则有大量的502报错。 502是Bad Gateway,Nginx的经典报错,首先想到的就是Gateway2不堪重负被Nginx在Upstream中踢掉。

那么,就先看看Gateway2的负载情况把,查了下监控,发现Gateway2在4核8G的机器上只用了一个核,完全看不出来有瓶颈的样子,难道是IO有问题?看了下小的可怜的网卡流量打消了这个猜想。

Nginx所在机器CPU利用率接近100%这时候,发现一个有意思的现象,Nginx确用满了CPU!

再次压测,去Nginx所在机器上top了一下,发现Nginx的4个Worker分别占了一个核把CPU吃满-_-!

什么,号称性能强悍的Nginx竟然这么弱,说好的事件驱动\epoll边沿触发\纯C打造的呢?一定是用的姿势不对!

去掉Nginx直接通信毫无压力既然猜测是Nginx的瓶颈,就把Nginx去掉吧。 Gateway1和Gateway2直连,压测TPS里面就飙升了,而且Gateway2的CPU最多也就吃了2个核,毫无压力。

去Nginx上看下日志由于Nginx机器权限并不在笔者手上,所以一开始没有关注其日志,现在就联系一下对应的运维去看一下吧。 在accesslog里面发现了大量的502报错,确实是Nginx的。 又看了下错误日志,发现有大量的

Cannot assign requested address由于笔者读过TCP源码,一瞬间就反应过来,是端口号耗尽了!由于Nginx upstream和后端Backend默认是短连接,所以在大量请求流量进来的时候回产生大量TIME_WAIT的连接。

而这些TIME_WAIT是占据端口号的,而且基本要1分钟左右才能被Kernel回收。

cat /proc/sys/net/ipv4/ip_local_port_range32768 61000也就是说,只要一分钟之内产生28232(61000-32768)个TIME_WAIT的socket就会造成端口号耗尽,也即470.5TPS(28232/60),只是一个很容易达到的压测值。 事实上这个限制是Client端的,Server端没有这样的限制,因为Server端口号只有一个8080这样的有名端口号。 而在upstream中Nginx扮演的就是Client,而Gateway2就扮演的是Nginx

为什么Nginx的CPU是100%而笔者也很快想明白了Nginx为什么吃满了机器的CPU,问题就出来端口号的搜索过程。

让我们看下最耗性能的一段函数:

int __inet_hash_connect(...){ // 注意,这边是static变量 static u32 hint; // hint有助于不从0开始搜索,而是从下一个待分配的端口号搜索 u32 offset = hint + port_offset; ..... inet_get_local_port_range(&low, &high); // 这边remaining就是61000 - 32768 remaining = (high - low) + 1 ...... for (i = 1; i <= remaining; i++) { port = low + (i + offset) % remaining; /* port是否占用check */ .... goto ok; } .......ok: hint += i; ......}看上面那段代码,如果一直没有端口号可用的话,则需要循环remaining次才能宣告端口号耗尽,也就是28232次。 而如果按照正常的情况,因为有hint的存在,所以每次搜索从下一个待分配的端口号开始计算,以个位数的搜索就能找到端口号。 如下图所示:

所以当端口号耗尽后,Nginx的Worker进程就沉浸在上述for循环中不可自拔,把CPU吃满。

为什么Gateway1调用Nginx没有问题很简单,因为笔者在Gateway1调用Nginx的时候设置了Keepalived,所以采用的是长连接,就没有这个端口号耗尽的限制。

Nginx 后面有多台机器的话由于是因为端口号搜索导致CPU 100%,而且但凡有可用端口号,因为hint的原因,搜索次数可能就是1和28232的区别

因为端口号限制是针对某个特定的远端server:port的。 所以,只要Nginx的Backend有多台机器,甚至同一个机器上的多个不同端口号,只要不超过临界点,Nginx就不会有任何压力。

把端口号范围调大比较无脑的方案当然是把端口号范围调大,这样就能抗更多的TIME_WAIT。 同时将tcp_max_tw_bucket调小,tcp_max_tw_bucket是kernel中最多存在的TIME_WAIT数量,只要port范围 - tcp_max_tw_bucket大于一定的值,那么就始终有port端口可用,这样就可以避免再次到调大临界值得时候继续击穿临界点。

cat /proc/sys/net/ipv4/ip_local_port_range22768 61000cat /proc/sys/net/ipv4/tcp_max_tw_buckets20000开启tcp_tw_reuse这个问题Linux其实早就有了解决方案,那就是tcp_tw_reuse这个参数。

echo '1' > /proc/sys/net/ipv4/tcp_tw_reuse事实上TIME_WAIT过多的原因是其回收时间竟然需要1min,这个1min其实是TCP协议中规定的2MSL时间,而Linux中就固定为1min。

#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT * state, about 60 seconds */2MSL的原因就是排除网络上还残留的包对新的同样的五元组的Socket产生影响,也就是说在2MSL(1min)之内重用这个五元组会有风险。 为了解决这个问题,Linux就采取了一些列措施防止这样的情况,使得在大部分情况下1s之内的TIME_WAIT就可以重用。 下面这段代码,就是检测此TIME_WAIT是否重用。

__inet_hash_connect |->__inet_check_establishedstatic int __inet_check_established(......){ ...... /* Check TIME-WAIT sockets first. */ sk_nulls_for_each(sk2, node, &head->twchain) { tw = inet_twsk(sk2); // 如果在time_wait中找到一个match的port,就判断是否可重用 if (INET_TW_MATCH(sk2, net, hash, acookie, saddr, daddr, ports, dif)) { if (twsk_unique(sk, sk2, twp)) goto unique; else goto not_unique; } } ......}而其中的核心函数就是twsk_unique,它的判断逻辑如下:

int tcp_twsk_unique(......){ ...... if (tcptw->tw_ts_recent_stamp && (twp == NULL || (sysctl_tcp_tw_reuse && get_seconds() - tcptw->tw_ts_recent_stamp > 1))) { // 对write_seq设置为snd_nxt+65536+2 // 这样能够确保在数据传输速率<=80Mbit/s的情况下不会被回绕 tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2 ...... return 1; } return 0; }上面这段代码逻辑如下所示:

在开启了tcp_timestamp以及tcp_tw_reuse的情况下,在Connect搜索port时只要比之前用这个port的TIME_WAIT状态的Socket记录的最近时间戳>1s,就可以重用此port,即将之前的1分钟缩短到1s。 同时为了防止潜在的序列号冲突,直接将write_seq加上在65537,这样,在单Socket传输速率小于80Mbit/s的情况下,不会造成序列号重叠(冲突)。 同时这个tw_ts_recent_stamp设置的时机如下图所示:

所以如果Socket进入TIME_WAIT状态后,如果一直有对应的包发过来,那么会影响此TIME_WAIT对应的port是否可用的时间。 开启了这个参数之后,由于从1min缩短到1s,那么Nginx单台对单Upstream可承受的TPS就从原来的470.5TPS(28232/60)一跃提升为28232TPS,增长了60倍。 如果还嫌性能不够,可以配上上面的端口号范围调大以及tcp_max_tw_bucket调小继续提升tps,不过tcp_max_tw_bucket调小可能会有序列号重叠的风险,毕竟Socket不经过2MSL阶段就被重用了。

不要开启tcp_tw_recycle开启tcp_tw_recyle这个参数会在NAT环境下造成很大的影响,建议不开启。

Nginx upstream改成长连接事实上,上面的一系列问题都是由于Nginx对Backend是短连接导致。 Nginx从 1.1.4 开始,实现了对后端机器的长连接支持功能。 在Upstream中这样配置可以开启长连接的功能:

upstream backend { server 127.0.0.1:8080;# It should be particularly noted that the keepalive directive does not limit the total number of connections to upstream servers that an nginx worker process can open. The connections parameter should be set to a number small enough to let upstream servers process new incoming connections as well. keepalive 32; keepalive_timeout 30s; # 设置后端连接的最大idle时间为30s}这样前端和后端都是长连接,大家又可以愉快的玩耍了。

由此产生的风险点由于对单个远端ip:port耗尽会导致CPU吃满这种现象。 所以在Nginx在配置Upstream时候需要格外小心。 假设一种情况,PE扩容了一台Nginx,为防止有问题,就先配一台Backend看看情况,这时候如果量比较大的话击穿临界点就会造成大量报错(而应用本身确毫无压力,毕竟临界值是470.5TPS(28232/60)),甚至在同Nginx上的非此域名的请求也会因为CPU被耗尽而得不到响应。 多配几台Backend/开启tcp_tw_reuse或许是不错的选择。

总结应用再强大也还是承载在内核之上,始终逃不出Linux内核的樊笼。 所以对于Linux内核本身参数的调优还是非常有意义的。 如果读过一些内核源码,无疑对我们排查线上问题有着很大的助力,同时也能指导我们避过一些坑!

猜你感兴趣
网购被骗怎么办(网购被骗怎么办不能退钱)

网购被骗怎么办(网购被骗怎么办不能退钱)

1、可以起诉网络交易平台2、消费者可以要求商家赔偿经验步骤:1可以起诉网络交易平台。该条款规定了电商平台的信息披露义务,给了消费者维权的新武器,这正是先进制度设计对消费者权益保护作用的良好体现,消费者应充分利用法律,维护好自己的合法权益...

精选综合 2023-05-12
哪些银行信用卡好办额度又高(哪些银行信用卡好批额度高)

哪些银行信用卡好办额度又高(哪些银行信用卡好批额度高)

银行信用卡审核主要看申请人的资信条件,资信条件越好,办信用卡越容易,额度也越高。如果申请人资信条件相同,选择以下银行信用卡好办额度又高:1、工商银行信用卡比较适合与工行有业务往来的人,在工行有资产,那么,办卡容易,且额度高,卡均额度有4...

精选综合 2023-05-12
磁铁衣服扣子对人体有害吗?(磁铁衣服扣子对人体有害吗)

磁铁衣服扣子对人体有害吗?(磁铁衣服扣子对人体有害吗)

磁铁衣服扣子对人体没有害。因为磁铁衣服扣子比较小,对身体是没有影响的。磁铁的成分是铁、钴、镍等原子,其原子的内部结构比较特殊,本身就具有磁矩。磁铁能够产生磁场,具有吸引铁磁性物质如铁、镍、钴等金属的特性。...

精选综合 2023-05-12
吃灵芝孢子粉大便发黑正常吗?

吃灵芝孢子粉大便发黑正常吗?

吃完灵芝孢子粉之后大便发黑在我们的日常生活中非常常见,实际上每个人吃完灵芝孢子粉之后,身上都会出现类似的现象,这正是表示起了效果,对人的身体健康没有其他的不良影响,灵芝孢子粉本身就是黑色的,就像吃了黑芝麻胡之后大便发黑一样,吃了灵芝孢子粉...

精选综合 2023-05-12
月见草的养殖方法和注意事项(月见草的种植方法和注意事项)

月见草的养殖方法和注意事项(月见草的种植方法和注意事项)

1、月见草的养殖方法:月见草喜光,适合栽培在庭院通风敞亮处,也可以养殖在阳台上,每天吸收太阳光照射。生长期间,每个月施1—2次液肥,生长期施肥以氮肥为主,孕蕾期以磷钾肥为主。2、月见草比较耐旱,但不耐涝,土壤表层见干时要及时浇水,每次...

精选综合 2023-05-12
注塑机调气纹的技巧有哪些

注塑机调气纹的技巧有哪些

注塑机调气纹的技巧有以下:1、模具透明法此法是将射胶时间一秒一秒增加,每增加一秒啤一啤,然后将每一啤未走齐的啤件按顺序排列起来,这样就可以很清楚地看到熔胶的充型过程,直到充满型腔为止。2、定位射胶法此法是将后一级的慢速和压力全部调整为零...

精选综合 2023-05-12
充分必要条件的口诀是什么(判断充分必要条件的口诀)

充分必要条件的口诀是什么(判断充分必要条件的口诀)

充分必要条件的口诀是:正推成立是充分,反推成立是必要。若有A推到B,则B为必要条件,即被推导出来的就是必要条件,不需要把两个一次性全部分辨出来。只要记准那个是必要条件就行了,因为另一个肯定就是充分条件。充分必要条件也即充要条件,意思...

精选综合 2023-05-12
为什么一般两年换手机(QQ为什么换手机登录不上去了)

为什么一般两年换手机(QQ为什么换手机登录不上去了)

原因:随着APP的功能越来越多,需要手机拥有更强大的性能才能流畅使用这些软件,因此需要定期更换手机才能获得最佳的使用体验。手机使用技巧:1、华为p30Pro具有抬手亮屏功能,打开华为p30Pro的系统设置页面,点击智能辅助――手势控制―...

精选综合 2023-05-12
肇事者不报警是全责吗?

肇事者不报警是全责吗?

肇事者不报警不一定是全责,交通事故的责任认定是由交警部门根据交通事故现场勘验、检查、调查情况和有关的检验、鉴定结论进行的。《道路交通安全法》第七十三条规定,公安机关交通管理部门应当根据交通事故现场勘验、检查、调查情况和有关的检验、鉴定结...

精选综合 2023-05-12
道姑的入观条件是什么

道姑的入观条件是什么

一般按要求需要高中以上文凭,但各地收容不一,需要准备身份证原件,当地派出所出具的无案底证明,自己写的出家自愿申请书及父母同意出家的同意书。一般出家考察期3年,如果合格出家,三年后师父会束发,冠巾等等才算是正规道士,正一本身就是散居道人,...

精选综合 2023-05-12
瑞虎5x电池型号是多少(瑞虎5x手动变速箱型号)

瑞虎5x电池型号是多少(瑞虎5x手动变速箱型号)

奇瑞瑞虎5x的电瓶型号有12V,60Ah(常规型号)和12V,70Ah(蓝驱车型)两种,类型为免维护式。汽车电瓶即为我们常说的蓄电池,瑞虎先前车型上的电瓶品牌有风帆的,也有选用骆驼品牌的电瓶。瑞虎5x的电瓶同大多数车型一样位于发动机舱...

精选综合 2023-05-12
中国银行周日上班吗?(中国银行周日上班吗?)

中国银行周日上班吗?(中国银行周日上班吗?)

中国银行周末上班,营业时间一般为8:00(或9:00)-16:30(或17:30),看各地的政府规定及本地城市的大小,自助银行是24小时营业;个人业务周末是不休息的(除了基金和银证业务以及个人贷款业务外),对公业务周末休息。具体到某一家...

精选综合 2023-05-12
洗衣机能放倒来运输吗?(波轮洗衣机能放倒运输吗)

洗衣机能放倒来运输吗?(波轮洗衣机能放倒运输吗)

1、洗衣机能放倒来运输吗?不能。2、因为这样对于缸筒或者滚筒都有伤害的。由于洗衣机有避震器,等于有软连接,所以,放倒后,缸筒会和外壳接触。对于滚筒来说,虽然有运输固定螺丝,但是内筒配重块非常重,而且一端固定在外壳,一端固定在缸筒外壳...

精选综合 2023-05-12
腊肉长蛆虫了还能吃吗?(腊肉长蛆虫了还能吃吗)

腊肉长蛆虫了还能吃吗?(腊肉长蛆虫了还能吃吗)

腊肉里长蛆虫了是不可以吃的,说明腊肉没有处理好,造成有虫卵遗留在腊肉中。腊肉里面长蛆虫说明里面已经可以适应寄生虫的生长环境,若吃了自然也会把寄生虫吃到肚子内造成寄生虫类疾病。...

精选综合 2023-05-12
黑金信用卡额度一般是多少(黑金信用卡要什么条件)

黑金信用卡额度一般是多少(黑金信用卡要什么条件)

黑金信用卡额度一般在200万到1000万之间。很多人认为,黑金信用卡额度没有上限,其实是误解,黑金信用卡的额度一般都在几百万元,而且可以根据持卡人的需求智能调节,但是黑金信用卡额度只能用于合理消费用途,不能作为企业流动资金。另外,有的...

精选综合 2023-05-12
芋艿发青了还能吃吗?(芋艿发黑了还能吃吗)

芋艿发青了还能吃吗?(芋艿发黑了还能吃吗)

芋艿发青了不要吃,因为芋艿发青的青色部分可能含有毒素,所以不能食用。正常成色的芋艿富含蛋白质、钙、磷、铁、钾、镁、钠、胡萝卜素、烟酸、维生素B1、维生素B2、皂角甙等多种成分。...

精选综合 2023-05-12
关于诚信交友的名言名句(关于诚信的名言名句大全)

关于诚信交友的名言名句(关于诚信的名言名句大全)

言必信,行必果。与朋友交,言而有信。人与人之间最大的信任就是关于进言的信任。学而不思则罔,思而不学则殆。人之相识,贵在相知,人之相知,贵在知心。...

精选综合 2023-05-12
转网不换号怎么办理(异地转网不换号怎么办理)

转网不换号怎么办理(异地转网不换号怎么办理)

1、拿起你的手机通过短信在线查询携转资格(短信编辑CCXZ#用户名#证件号码,发送至归属运营商,移动10086,联通10010,电信10001)。2、用户通过短信申请授权码(短信指令:SQXZ#用户名#证件号码,发送至归属运营商,移动1...

精选综合 2023-05-12
铁棍山药麻嘴能吃吗?(铁棍山药麻嘴能吃吗)

铁棍山药麻嘴能吃吗?(铁棍山药麻嘴能吃吗)

铁棍山药麻嘴是可以吃的,只要把山药表面的皮去掉,然后洗干净就是没问题的。铁棍山药中含少量的植物碱,对人身也是有好处的,但有些过敏体质的人会对这种碱性物质过敏,导致食用后嘴里发麻。...

精选综合 2023-05-12
藏南人民用哪国身份证

藏南人民用哪国身份证

藏南人民以实际控制线为界一边用印度的身份证,一边用中国的身份证。事实上,尽管多年来中印边界从未正式划定,但两国人民在长期和平友好相处过程中,按照双方的行政管辖范围,已经形成了一条为两国人民都尊重的传统习惯线。...

精选综合 2023-05-12