
随着携程的应用大规模在生产上用容器部署,各种上规模的问题都慢慢浮现,其中比较难定位和解决的就是偶发性超时问题,下面将分析目前为止我们遇到的几种偶发性超时问题以及排查定位过程和解决方法,希望能给遇到同样问题的小伙伴们以启发。问题描述

某一天接到用户报障说,Redis集群有超时现象发生,比较频繁,而访问的QPS也比较低。紧接着,陆续有其他用户也报障Redis访问超时。在这些报障容器所在的宿主机里面,我们猛然发现有之前因为时钟漂移问题升级过内核到4.14.26的宿主机ServerA,心里突然有一丝不详的预感。初步分析

因为现代软件部署结构的复杂性以及网络的不可靠性,我们很难快速定位“connect timout”或“connectreset by peer”之类问题的根因。历史经验告诉我们,一般比较大范围的超时问题要么和交换机路由器之类的网络设备有关,要么就是底层系统不稳定导致的故障。从报障的情况来看,4.10和4.14的内核都有,而宿主机的机型也涉及到多个批次不同厂家,看上去没头绪,既然没什么好办法,那就抓个包看看吧。

图1

图2图1是App端容器和宿主机的抓包,图2是Redis端容器和宿主机的抓包。因为APP和Redis都部署在容器里面(图3),所以一个完整请求的包是B->A->C->D,而Redis的回包是D->C->A->B。

图3上面抓包的某一条请求如下:
B(图1第二个)的请求时间是21:25:04.846750 #99
到达A(图1第一个)的时间是21:25:04.846764 #96
到达C(图2第一个)的时间是21:25:07.432436 #103
到达D(图2第二个)的时间是21:25:07.432446 #115
该请求从D回复如下:
D的回复时间是21:25:07.433248 #116
到达C的时间是21:25:07.433257 #104
到达A点时间是21:25:05:901108 #121
到达B的时间是21:25:05:901114 #124
从这一条请求的访问链路我们可以发现,B在200ms超时后等不到回包。在21:25:05.055341重传了该包#100,并且可以从C收到重传包的时间#105看出,几乎与#103的请求包同时到达,也就是说该第一次的请求包在网络上被延迟传输了。大致的示意如下图4所示:

图4从抓包分析来看,宿主机上好像并没有什么问题,故障在网络上。而我们同时在两边宿主机,容器里以及连接宿主机的交换机抓包,就变成了下面图5所示,假设连接A的交换机为E,也就是说A->E这段的网络有问题。

图5陷入僵局

尽管发现A->E这段有问题,排查却也就此陷入了僵局,因为影响的宿主机遍布多个IDC,这也让我们排除了网络设备的问题。我们怀疑是否跟宿主机的某些TCP参数有关,比如TSO/GSO,一番测试后发现开启关闭TSO/GSO和修改内核参数对解决问题无效,但同时我们也观察到,从相同IDC里任选一台宿主机Ping有问题的宿主机,百分之几的概率看到很高的响应值,如下图6所示:

图6同一个IDC内如此高的Ping响应延迟,很不正常。而这时DBA告诉我们,他们的某台物理机ServerB也有类似的的问题,Ping延迟很大,SSH上去后明显感觉到有卡顿,这无疑给我们解决问题带来了希望,但又更加迷惑:
延迟好像跟内核版本没有关系,3.