前言作为阿里云提供的基础设施,内部的物理网络和很多网络产品在数据平面对于客户来说是不可操作的,某种程度上是一个黑匣子。当然,在传统的IDC环境下,业务和物理网络之间同样存在差距。所以在业务卡顿、延迟或阻塞的情况下,很容易怀疑网络。所以,如何拿出丝和茧,找准方向对症下药,才能真正解决问题。毕竟“真理只有一个”。
在排查和处理问题的时候,最难的场景就是极偶发性和极低重现频率的问题。尤其是在网络故障排除领域,通常出于性能和资源消耗控制的考虑,不会一一记录每一个数据包。对于应用层记录的一次偶然的超时,网络层通常没有明确的记录这个应用层调用对应的分组交互,因此故障排除非常困难。
在这种情况下,我们通过一个客户端查询redis集群偶尔超时的小案例,说明一些诊断思路和故障排除方法,然后引出一些提高网络业务稳定性的最佳实践。
这次的问题是一个交互式web应用的子模块,主要进行redis查询。可以简单理解为视频弹幕网站中“查询弹幕”的一个小模块。该模块的拓扑非常简单:
在上面的拓扑结构中,客户使用ECS构建了一个Redis集群,在前端实现了一层带有Codis的Redis代理(为了通用起见,在后端使用Redis代理),将这组Redis代理挂载在一个SLB上,通过SLB的单一门户提供服务。
问题客户的主要问题是访问其自建Redis系统的客户会偶尔超时报错。虽然整体概率不高,但报错概率比他们在原机房运行的业务要高。超时错误报告主要有两种情况:
一般来说,超时次数与业务量正相关,但在非高峰业务时段,SLB和ECS的资源利用率较低。会突然出现很多暂停。诊断思维作为故障排除的第一步,首先要了解问题本身的来龙去脉和环境。在平时收集诊断问题的信息时,为了系统全面地收集信息,作者将需要收集的信息分为两种:资源因素和环境因素。
资源因素:出现问题的系统的拓扑结构。例如各种应用、主机、转发设备、链路资源等。参与,并充分理解这些资源在拓扑中的作用。环境因素:描述该问题所需的信息,如错误日志、问题发生的时间和频率、应用层设置的超时等。在了解了资源因素和环境因素后,我们可以将问题定义为:在哪些资源上发生了什么样的问题,然后根据这个定义收集与问题相关的信息,在解读和分析时通过数据排除一切不可能,从而进行高效准确的问题排查。
本案例中,资源因素在上面的拓扑中已经解释过了,问题涉及的环境因素包括:客户设置了50ms超时,客户端上报的错误为读取超时(代表不含tcp的三次握手超时),非业务高峰时段错误上报频率为一小时10个左右,业务高峰时段一小时上百个。但偶尔(一周一到两次)会有更多,上百倍的读取超时和连接超时,无论业务高峰还是非业务高峰。客户查过redis,每次查询时间小于10ms,而redis代理不记录转发的日志。
方法因为所有可用的日志只能位于该系统的两端(客户端、Redis),所以需要收集进一步的信息。面对这种超时问题,最直接有效的方法就是抓包。不过这个问题出现的频率不高,整个系统的流量也比较大。很容易一直用数据包捕获填满磁盘,因此有必要使用循环数据包捕获:
Tcump-I接口|any -C每文件大小-w文件数量-W保存文件名,抓取数据包和过滤条件。这个命令的意思是,对于一个接口,根据过滤条件抓取数据包,用指定的文件名前缀保存文件,这样会占用高达每个文件大小*文件个数的磁盘空间,循环覆盖。循环包捕获启动后,等待客户端错误再次出现,就可以当场捕获包交互过程。
数据包捕获的结果文件可以用wireshark打开,但是循环数据包捕获捕获的数据包文件很大,数量很多,所以可以使用以下提示快速过滤:
//安装了wireshark的电脑上有两个命令,capinfos和tshark。以笔者使用的macOS为例~ $ capiinfos-a-e * cap//使用capiinfos检查包捕获文件的实际时间和结束时间,选择包含报错时间-超时时间的文件。其他文件是不必要的:文件名: colasoft _ packets.cap包大小限制3360已感染3360 66字节-1518字节(范围)首包时间: 2019-06-12 09:00003336 000.00055519936最后一个包时间: 2019-06-12 093333365capPacket大小限制:推断: 60字节- 1518字节(范围)2019年6月12日第一个包时间: 093336351最后一个包时间: 2019年6月12日。//如果还有更多文件,可以用tshark命令过滤掉,20848.000000000845例如,如果错误中提到Redis查询一个键超时,可以用下面的脚本找出这个查询请求在哪个文件中:~$ for f in。/*;do echo $ f;tshark -r $f ‘tcp.payload包含“keyname\ ”;done找到对应的请求后,用wireshark打开文件,找到对应的数据包,跟踪对应的流,找到五元组和整个流之间的上下文交互。
在这种情况下,通过对比客户端、redis代理和redis的包捕获,发现问题发生时从客户端请求到响应的时间确实大于100 ms,而这种耗时主要是因为Redis因丢包重传而向Redis代理返回响应而产生的。总体时序图如下:
对于从包捕获中观察到的丢包现象,当通过阿里云内部监控确定物理链路没有丢包时,我们发现当虚拟化级别的后端驱动向Redis代理所在的ECS上的前端驱动发送包时,前端队列和后端队列中丢包计数的增加趋势与服务超时的频率具有相同的趋势。进一步调查显示,客户的ECS操作系统中的多个网卡队列未打开。只有一个CPU处理网卡中断,当流量突然增大时,CPU来不及处理网卡中断,导致前后队列堆积,队列溢出导致丢包。
要解决这个问题,我们建议客户开放多个网卡队列,将不同网卡队列的CPU亲和力绑定到不同的CPU上。对于阿里云ECS来说,可以使用的网卡队列是绑定到实例规范的。有关详细信息,请参考ECS实例规范文档。简单打开网卡队列,用irqbalance自动调度网卡队列中断CPU亲和的方法,可以参考阿里云官方文档。
https://help.aliyun.com/document_detail/52559.html
在这种情况下,客户启动网卡多队列和irqbalance服务后,每小时访问超时问题已经解决,但每隔几天仍会出现大量的突然超时。在收集了客户的错误信息和阿里云的网络监控后,我们最终确认,每隔几天出现的突然大量超时是由于阿里云可用区间内的链路抖动造成的。
阿里云的每个可用区域可以理解为一个机房,不同的可用区域之间可以有同城容灾关系。为了保证可用区域之间不会出现故障传播,不同可用区域的机房需要保持一定的物理机距,所有可用区域通过同一条同城传输光缆相互连接,实现可用区域之间的互访。
可用区域之间同城传输光缆的可靠性远低于机房跳纤,而且往往容易受到道路施工和质量恶化的影响,导致链路中断。为了保证业务的连续性,阿里云提供了足够的冗余链路,并使用传输交换、路由交换等技术,保证一些跨越可用区域的链路能够自动收敛,但交换过程中的丢包无法完全避免。根据阿里云的底层监测,当一条跨可用区域的链路中断时,通常会导致持续3-5秒的1%左右的丢包(取决于中断链路占链路总数的比例),反映到业务中,可能会造成一些接近1分钟的延迟敏感业务的超时错误。因此,在这种情况下,它造成了超时错误的突然增加。
如果客户使用资源,可用区域分布非常分散,会增加可用区域内链路抖动造成服务影响的频率。例如,如果客户的客户端ECS分布在多个可用区域(A和B),SLB在可用区域C,Redis代理和Redis在可用区域D和E,则跨可用区域A到C、B到C、C到D和D到E的链路抖动将影响整个系统。
最佳实践通过这个案例,我们可以总结出主机网络和网络部署两个最佳实践:
主机:开放网卡多队列,打散网卡软中断,获得最佳网络性能。一般来说,要想获得稳定的网络性能,一般建议有以下几点:使用VPC实例:除了网络租户隔离、支持专线、VPN网关等优势外,VPC环境与经典网络实例相比,大大提高了底层的转发能力。最新一代实例全部基于VPC环境,因此也提供了更强的网络转发性能。使用独占实例:独占实例采用严格的资源隔离技术,保证虚拟机不会受到“吵闹邻居”的影响。打开网卡的多个队列,绑定到CPU亲和力进行软中断处理:网卡的不同队列由不同的CPU处理,提高网络处理性能。网卡的多个队列绑定到一些专用CPU,而其他进程绑定到其他CPU,这样网卡的软中断处理就可以由专用CPU来处理。适用于对网络性能要求较高的纯转发业务。//如何绑定网卡软中断://1。先看cat /proc/interrupts | grep virtio,在阿里云提供的标准操作系统中,Virtuo0是网卡队列~ $ cat/proc/interrupts | grep virt io//Omi outputs 313360 310437168 000 PCI-MSI-edge virt io 0-input . 0 323360 34644209 000 PCI-MSI-edge virt io 0-output . 0//记录第一列的中断号,下面的文件绑定CPU物理方面:建议权衡业务容忍度和延迟敏感度来选择业务部署。从业务容忍度的角度来看,如果tcp协议发生丢包,最坏情况下需要等待RTO超时后再重传(尾丢场景,其他场景有快速重传机制),RTO超时的最小值定义为200HZ,即内核中的200ms。对于低延迟的网内访问或城际访问的场景,可以理解为丢包的最坏情况是重传200ms。因此,对于关键服务,请求超时应至少设置为200ms,以便tcp有机会重新传输。对于非关键业务,查询是否返回数据并不重要,因此可以将请求超时设置得更小,以保护整个系统。因此,业务容忍度有两个方面:业务可以容忍错误,或者业务可以容忍重传。从时延敏感的角度来看,为了保证时延敏感业务尽可能少地受到跨越可用区域的链路的影响,建议时延敏感业务的整个业务调用尽量在一个可用区域内完成。然而,尽管不同的可用区域提供相同的服务,但是它们不经常被跨可用区域调用。比如web服务器层调用提供缓存服务的Redis在这个可用区域完成。只有当存在少量缓存未命中时,才有可能跨可用区域查询数据库,甚至使用只读实例等其他技术来最小化跨可用区域的链路抖动的影响。结论通过以上案例和最佳实践,我们可以看到,在业务系统架构和部署中,“取舍”无处不在。所谓优化,就是将资源向最需要的地方倾斜,以便在给定的环境下实现业务目标。另一方面,由于上云前系统架构的限制,机房的成本和位置等因素,很多客户可能不会使用太多的机房组网场景。云计算除了方便基础设施的跨代升级,还为这些客户提供了自然容灾,业务系统的架构和部署也需要增加容灾带来的组网场景的复杂性。
作者:杰里岳斌
暂无讨论,说说你的看法吧