第一次发现这个问题,应该是在很早之前,我本地用浏览器访问我们公司的业务网站,发现有时很快,有时达到8、9秒以上,但是也没有太在意,以为是偶尔一次的。另外我用手机4G网络也测试访问了下,速度挺快的。
这里要自我检讨下,发现问题时,我投机取巧的去掩盖问题,而没有去正视这个问题。这种态度是要不得的。不然问题会像滚雪球一样可怕!!!
环境介绍分析及测试环境介绍
这里我介绍下整体的大致环境,这几台业务主机上,每台主机都有一个nginx,用于处理虚拟主机。然后最上面有一个公网LB(负载均衡器)。它负责接收外部的流量,终止ssl,均衡的分发请求到每个主机的nginx上。
还有一点需要介绍下,我们线上还有一个公网LB,也是转发流量到这几台主机nginx上。这俩LB的区别只是加载的域名ssl证书不一样,其它配置一摸一样(让我一直在纠结是LB配置的原因)。最后就是监控系统是部署在容器集群里的(很大程度的迷惑了自己,我曾以为是容器网络出现了延时问题…)。
分析
当时想了以下几个点:
测试公网LB配置错误
Jun1516:45:2918.19.1.12haproxy[30952]:139.1.2.3:61653[15/Jun/2018:16:45:08.784]lbl-ckv7ynro~lbl-ckv7ynro_default/lbb-izjpmxrh327/15003/-1/-1/20331503213--sCNN4/3/0/0/+30/0"HEAD/sessions/authreturn_to=%2FHTTP/1.1"
以前没咋看过haproxy日志,nginx日志倒是都明白,这一看傻眼了。查查文档吧。下面是对每段的解释:
针对这个的测试,我准备在夜间流量低峰时,暂时禁用掉其它的LB后端,只保留1台后端主机进行对外服务。很快的我发现这也行不通。问题依旧会出现。逐个的去替换,这一个测试没效果。
监控系统部署所在集群的网络问题
做这个测试时,我还请了外援。让别人在他们公司内部帮忙用ab访问下。分别是外部联通、外部电信、Google云主机、VPC内部。下面是ab针对域名访问的结果。LB1:lb1.example.comLB2:lb2.example.com
LB1的ab测试结果:
LB2的ab测试结果:
VPC内部测试(统一出口):
忘记说了一件事,我也在nginx主机上和vpc内部其它主机上通过修改请求header,直接访问内部IP请求资源,这里是没有问题的,响应特别快。这又能证明主机上服务运行良好。网络也可以排除。这……悲剧了。
应用主机系统参数有问题后来请教别人,最后告诉我看看内核参数recycle。然后我又去网上查了下,看看有没有类似的问题,但是不好查啊,环境都不一样。
但是最后查到一条关于nat环境下,在应用服务器上设置内核参数时,启用了net.ipv4.tcp_tw_recycle和net.ipv4.tcp_tw_reuse。按照这个思路导致有些客户端连接服务器失败,根据这个我去看了下服务器的配置,果不其然,有这个参数的优化。
验证结果
在手动的执行下面这条命令后:
sysctl-wnet.ipv4.tcp_tw_recycle
继续在vpc网络内部测试,发现对该LB的ab测试全部都正常了,真是应了那句话,差不多一切的问题不是网络问题就是配置问题。下面是修改前后的监控对比图:
分析根本原因
这里提出了2个问题,便于理解记忆全文。
为什么启用这个tcprecycle?
这个是之前在部署应用主机系统时,修改优化了部分内核参数,当时想的是为了增大主机对tcp的连接性能,防止遇到并发用户的连接,导致tcp连接不能快速释放,从而引发服务器出现性能上的瓶颈(会导致服务器内存和CPU的暴增)。
另外关于time_wait具体的可以参考tcp的4次断开后的状态。所以为了快速回收和重新使用,才开启了tcp的reuse和recycle。但没想到这个会引起这么大的问题。并且这个参数之前确实也在前公司用过。但没有发现这个类似的问题(也可能是当时的监控不到位,没有发现也不代表该问题不存在)。这里是官方内核文档对这俩参数的解释:
net.ipv4.tcp_tw_recycle:EnablefastrecyclingTIME-WAITsockets.Defaultvalueis0.Itshouldnotbechangedwithoutadvice/requestoftechnicalexperts.net.ipv4.tcp_tw_reuse:AllowtoreuseTIME-WAITsocketsfornewconnectionswhenitissafefromprotocolviewpoint.Defaultvalueis0.Itshouldnotbechangedwithoutadvice/requestoftechnicalexperts.
为什么会阻塞客户端(Nat环境)请求?
上面说了为什么启用它,现在在讨论下,为什么启用它后,会导致部分用户的链接,而不是全部?看了一些文档及别人提到的解释:
为什么我看不到关于connecttimeout的错误呢?因为在这个环境下,client相当于是最前面的LB,即haproxy,从这里也很好的解释了,为什么haproxy的日志有很多连接重试的记录!
因为在NAT(网络地址转换)环境下,有很多的client,流量进出都是通过一个公网IP出去的。
TokeepthesameguaranteestheTIME-WAITstatewasproviding,whilereducingtheexpirationtimer,whenaconnectionenterstheTIME-WAITstate,thelatesttimestampisrememberedinadedicatedstructurecontainingvariousmetricsforpreviousknowndestinations.Then,Linuxwilldropanysegmentfromtheremotehostwhosetimestampisnotstrictlybiggerthanthelatestrecordedtimestamp,unlesstheTIME-WAITstatewouldhaveexpired总结
不要开启tcp_tw_recycle,重要的话说三遍。一定要有配置管理!可以方便在系统出问题时,检查对主机所做的历史记录。考虑问题不能光从软件程序、网络上,还要加入对主机系统的分析。tcpdump、ss、还有log等。