对于云上的用户来说,业务日志里面报超时问题处理起来往往比价棘手,因为1) 问题点可能在云基础设施层,也有可能在业务软件层,需要排查的范围非常广;2) 这类问题往往是不可复现问题,抓到现场比较难。在本文里就分析下如何来分辨和排查这类问题的根本原因。
业务超时 != 网络丢包
由于业务的形态不同,软件实现语言和框架的不同,业务日志中打印出的信息可能是各不相同,比如如下关键字:
"SocketTimeOut", "Read timed out", "Request timeout" 等
从形式看都属于网络超时这一类,但是需要明确一个概念:这类问题是发生的原因是请求超过了设定的timeout时间,这个设置有可能来自客户端,服务器端或者网络中间节点,这是直接原因。网络丢包可能会导致超时,但是并不是充分条件。总结业务超时和网络丢包的关系如下:
网络丢包可能造成业务超时,但是业务超时的原因不一定是丢包。
明确了这个因果关系后,我们再来看怎么分析业务超时。如果武断地将业务超时等同于网络抖动丢包,那这个排查分析过程就完全错过了业务软件层本身的原因,很容易进入困局。
本文会从云基础设施层和业务软件层对业务超时做分析,总体来讲基础设置层面的丢包原因相对容易排查,阿里云有完善的底层监控,根据业务日志报错的对应时间段,从监控数据中可以确定是否有基础设施网络问题。而业务层的超时通常是软件层面的设置,和软件实现及业务形态都有关系,这种往往是更加难以排查的。
网络丢包为什么导致业务超时
网络抖动可能造成业务超时,其主要原因是网络抖动会带来不同程度的延迟。本文以互联网大部分应用以来的TCP为对象来介绍,一个丢包对数据传输的完整性其实是没有影响的,因为TCP协议本身已经有精密的设计来处理丢包,乱序等异常情况。并且所有重传的处理都在内核TCP协议栈中完成,操作系统用户空间的进程对这个处理实际上是不感知的。丢包唯一的副作用的就是会增加延迟,如果这段延迟的时间足够长,达到了应用进程设置的某个Timeout时间,那么在业务应用侧表现出来的就是业务超时。
丢包出现时会不会发生超时,取决于应用进程的Timeout设置。比如数据传输中的只丢了一个TCP数据包,引发200 ms后的超时重传:
- 如果应用设置的Timeout为100 ms,TCP协议栈没有机会重传,应用就认为超时并关闭连接;
- 如果应用设置的Timeout为500ms,则TCP协议栈会完成重传,这个处理过程对应用进程透明。应用唯一的感知就是处理这次报文交互比基线处理时长多了200ms,对于时间敏感度不是非常高的应用来说这个影响非常小。
延迟到底有多大?
在设置应用进程Timeout时间时有没有可以参考的定量值呢?虽然TCP中的RTT/RTO都是动态变化的,但TCP丢包的产生的影响可以做一定的定量总结。
对丢包产生的延迟主要有如下两类:
- TCP建连超时。如果网络抖动不幸丢掉了TCP的第一个建连SYN报文,对与不太老的内核版本来说,客户端会在1秒(Draft RFC2988bis-02中定义)后重传SYN报文再次发起建连。1秒对于内网环境来说非常大,对于阿里云一个区域的机房来说,正常的RTT都是小个位数毫秒级别,1秒内如果没有丢包足够完成百个数据报的交互。
- TCP