时延敏感业务低概率超时问题分析

前言

作为阿里云底层提供的基础设施,内部的物理网络和许多网络产品在数据平面给客户的可操作性并不高,从一定程度上来说是个黑盒。当然,在传统的IDC环境,业务和物理网络之间也存在同样的隔阂。所以在遇到业务卡顿、延迟、不通等问题的时候,很容易怀疑到网络。因此如何抽丝拨茧,找到正确的方向对症下药才能够真正的解决问题。毕竟“真相只有一个”。

在进行问题排查和处理的时候,难度最高的场景就是极度偶发,复现频率极低的问题。尤其在网络排查的领域,通常为了性能和控制资源消耗,不会将每一个数据包的情况都一一记录下来,对于一次偶发的应用层记录的超时,网络层通常没有明确的对应此次应用层调用的包交互记录,因此排查起来非常困难。

在这次的案例中,我们通过一个客户端查询redis集群偶发超时的小案例,来说明一些诊断思路、排查手段,进而引出一些在网络方面提高业务稳定性的最佳实践。

问题环境

这次的问题是一个交互性web应用中的一个子模块,主要进行redis查询,可以简单将其理解为视频弹幕网站中“查询弹幕”的小模块。这个模块的拓扑非常简单:

在上面的拓扑中,客户使用ECS构建了一个Redis集群,前面用Codis实现了一层Redis Proxy (为了通用性,后面均用Redis proxy来描述),并将这组Redis proxy挂载在一个SLB后,通过SLB的单一入口提供服务。

问题现象

客户的主要问题是访问其自建Redis系统的客户端会不定期出现超时报错,尽管总体概率不高,但是报错概率高于其业务运行在原有机房的水平。超时报错主要有两种情况:

  1. 一般情况下超时数量与业务量呈正相关,非业务高峰期但是SLB、ECS的资源使用率均较低。
  2. 会存在突发性的大量超时。

诊断思路

作为问题排查的第一步,首先要了解到问题本身所处的上下文和环境。在平时诊断问题收集信息的时候,为了有条理的、全面的收集信息,笔者将需要收集的信息分为两种类型:资源因素和环境因素。

  • 资源因素:即发生问题的系统的拓扑。比如涉及的各种应用程序、主机、转发设备、链路资源等,并且要充分理解这些资源组建在拓扑中起到的作用。
  • 环境因素:即描述这个问题所需要的信息,比如报错日志,问题发生时间、频率,应用层设置的超时时间等等。

了解资源因素和环境因素后,可以将问题的定义明确为:在哪些资源上发生了什么样的问题,然后根据该定义收集与问题相关的信息,并在解读和分析的时候通过数据排除所有的不可能,这样才能进行高效和准确的问题排查。

在本案例中,资源因素已经在上文的拓扑中阐述,问题所涉及的环境因素包括:客户设置的是50ms超时,在客户端的报错是read timeout(代表排除了tcp的三次握手超时),报错频率为非业务高峰期一个小时10个左右,业务高峰期1小时上百个。但是偶尔(一周内偶尔发生一次到两次)无论业务高峰还是非业务高峰都会有较多的,上百次的read timeout和connect timeout。客户已经排查过redis,其查询时间每次耗时不超过10ms,而redis proxy没有记录转发的日志。

排查方法

因为所有可用的日志仅能定位到这个系统的两端(客户端、Redis),需要收集进一步的信息。面对这种超时类的问题,最直接、有效的办法就是进行抓包。而该问题发生的频率不高,整个系统流量也比较大,一直开着抓包很容易将磁盘撑满,因此需要使用循环抓包:

tcpdump -i <接口|any> -C <每文件大小> -W <文件个数> -w <保存文件名> 抓包过滤条件

该命令的意思是针对某个接口,按照过滤条件进行抓包,保存指定文件名前缀的文件下,最多占用每文件大小*文件个数 的磁盘空间并循环覆盖。开启循环抓包后,等待客户端报错再次出现,即可抓到现场的包交互过程。

抓包的结果文件可以使用wireshark打开,但是使用循环抓包抓到的数据包文件较大、数量较多,可以使用下面的小技巧进行快速的过滤:

//在安装了wireshark的电脑上都会有capinfos和tshark两个命令,以笔者使用的macOS为例
~$ capinfos -a -e *cap //使用capinfos查看抓包文件的其实时间和结束时间,选取包含报错时间+-超时时间的文件,其他文件就不需要了
File name:           colasoft_packets.cap
Packet size limit:   inferred: 66 bytes - 1518 bytes (range)
First packet time:   2019-06-12 09:00:00.005519934
Last packet time:    2019-06-12 09:59:59.998942048File name:           colasoft_packets1.cap
Packet size limit:   inferred: 60 bytes - 1518 bytes (range)
First packet time:   2019-06-12 09:00:00.003709451
Last packet time:    2019-06-12 09:59:59.983532957//如果依然有较多文件,则可以使用tshark命令进行筛选。比如报错中提到Redis查询一个key超时,则可以用以下脚本找到这次查询请求具体在哪个文件中:
~$ for f in ./*; do echo $f; tshark -r $f 'tcp.payload contains "keyname"'; done

找到对应的请求之后,再用wireshark打开该文件,找到对应数据包,跟踪对应流来找到五元组和整个流的上下文交互。

在本案例中,通过对比客户端、redis proxy和redis 三层的抓包,发现客户端发出请求到收到响应的时间的确在问题发生时话费了100多ms,而这部分耗时主要发生在Redis将响应返回给Redis proxy的丢包重传导致。整体时序示意图如下:

 

对于从抓包中观察到的丢包现象,在通过阿里云内部监控确定了物理链路的确不存在丢包的情况下,我们发现Redis proxy所在的ECS上,虚拟化层面的后端驱动在向前端驱动送包的时候,前后端队列的丢包计数的增长趋势和业务超时的频率有相同趋势,进一步排查发现客户ECS操作系统内的网卡多队列没有开启,导致只有一个CPU处理网卡中断,而当流量有瞬间突增的时候,CPU来不及处理网卡中断导致前后端队列堆积,队列溢出后导致丢包。

为了解决这个问题,我们建议客户将网卡多队列开启,并将不同网卡队列中断的CPU亲和性绑定在不同的CPU上。对于阿里云ECS,可以使用的网卡队列是和实例规格绑定的,具体可以参考ECS实例规格文档。简单的开启网卡队列并使用irqbalance 自动调度网卡队列中断CPU亲和性的方法可以参考阿里云官方文档。

本案例中客户开启网卡多队列并开启irqbalance服务之后,每小时都出现的访问超时问题已经解决,但是还是会有每隔几天会出现的突发性大量超时。经过汇聚客户的报错信息和阿里云底层的网络监控,我们最终确认这种每隔几天就会出现的突发性大量超时是因为阿里云底层的跨可用区间链路抖动导致的。

阿里云的每一个可用区可以理解为是一个机房,而不同可用区之间可以互为同城灾备关系。为了确保可用区之间不会故障扩散,不同可用区机房需要保持一定物理机距离,并通过同城传输光缆将所有可用区相互连接实现可用区之间的互访。

连接可用区之间的同城传输光缆的可靠性远低于机房内部跳纤,且经常容易受到道路施工、质量劣化的影响,导致链路中断。为了保证业务连续性,阿里云提供了充足的冗余链路并使用传输倒换、路由切换等技术确保部分跨可用区链路时故障可以自动收敛,但是在倒换过程中产生的丢包却无法完全避免。根据阿里云底层监控,当一条跨可用区链路中断时,通常会导致持续3-5秒的1%左右的丢包(具体需要看中断链路数量占总链路数量的占比),而反映在业务上,则有可能造成时延敏感业务接近1分钟的部分超时报错。因此在本案例中造成了突增的超时报错。

假如客户使用资源时,可用区分布非常散乱,则会造成可用区间链路抖动对业务影响的频率升高。比如客户的客户端ECS分布在多个可用区(A、B),SLB在可用区C ,Redis proxy和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,在阿里云提供的标准操作系统中,virtio0是网卡队列
~$cat /proc/interrupts  | grep virtio
//omit outputs31:  310437168          0          0          0   PCI-MSI-edge      virtio0-input.032:  346644209          0          0          0   PCI-MSI-edge      virtio0-output.0
//将第一列的中断号记录下来,修改下面的文件绑定CPU亲和性
echo <cpu affinity mask> /proc/irq/{irq number}/smp_affinity
//具体CPU affinity mask可以参考manpage https://linux.die.net/man/1/taskset,这里不再说明。
  • 物理网络方面:建议从业务容忍度和时延敏感度进行权衡来选择业务的部署。
  • 从业务容忍度的角度来说,如果tcp协议中发生了丢包,那么最坏情况下需要等待RTO超时才能够重传(tail drop场景,其他场景有fast retrans机制),而RTO超时的最小取值在kernel中的定义为200HZ,即200ms。对于内网互访或者同城互访这种时延较低的场景,可以理解为一次丢包的最坏情况就是200ms的重传,因此对于关键业务,至少将请求超时设置在200ms以上,让tcp有一次重传的机会。而对于非关键业务,一次查询是否返回数据并不关键的,则可以将请求超时设置的更小以便保护整个系统。因此业务容忍有两个方面:业务可以容忍错误,或者业务可以容忍重传。
  • 从时延敏感度的角度来说,为了确保时延敏感业务尽量少的受跨可用区链路影响,建议尽量将时延敏感业务的整个业务调用都在一个可用区内完成。而不同的可用区之间尽管提供相同服务,但是之间不会经常跨可用区调用。比如web server层调用提供缓存服务的Redis在本可用区完成,只有缓存没有命中的少量情况,才有可能跨可用区查询数据库,甚至使用只读实例等其他技术,将跨可用区链路抖动的影响降至最低。

结束语

通过上面的案例和最佳实践的说明,可以看到“权衡”在业务系统架构涉及和部署当中是无处不在的。所谓优化就是在给定的环境下,为了实现业务目标,将资源倾斜到最需要的地方。另一方面,对于许多客户在上云前的系统架构中,受限与机房成本、位置等原因,可能没有使用过多机房的组网场景,而云计算对这些客户带来的除了基础设施跨代升级的便利之外,还提供了天然的容灾能力,而业务系统的架构和部署也需要增加因容灾所带来的组网场景的复杂化。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518656.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java-数组 三种初始化及内存分析

声明的时候数组并不存在&#xff0c;创建的时候数组才真正的存在 数组初始化 除了八大基本类型&#xff0c;其他都是引用类型 public class ArrayDemo02 {public static void main(String[] args) {// 静态初始化&#xff1a; 创建 赋值int[] a {1,2,3,4};System.out.print…

十分钟上线 - 函数计算构建支付宝小程序的后端

阿里云函数计算服务(FunctionCompute&#xff0c;FC)是一个事件驱动的全托管计算服务。通过函数计算与云端各个服务的广泛集成&#xff0c;开发者只需要编写函数代码&#xff0c;就能够快速地开发出弹性高可用的后端系统。接下来我们使用FC&#xff0c;来快速实现一个图片转换服…

用Java开发自己的Kubernetes控制器,想试试吗?

作者 | Nicolas Frnkel译者 | 天道酬勤 责编 | 徐威龙封图| CSDN 下载于视觉中国在本文中&#xff0c;我们将开始开发自己的Kubernetes控制器。 技术栈可以是Python、NodeJS或Ruby。因为这个博客被命名为为“ Java极客”&#xff0c;因此选择Java是很正常的。 作为一个用例&…

SpringBoot 扫描包

文章目录1. 默认扫描2.指定扫描3.指定扫描21. 默认扫描 默认扫描&#xff1a; 在启动类WikiApplication上的SpringBootApplication注解&#xff0c;默认SpringBoot 扫描范围是当前包(com.gblfy.wiki)以及子包controller包等等 2.指定扫描 扫描项目包但不能扫描第三方的包&a…

揭秘阿里云背后神秘而富有能量的一群人

作为某创业公司CTO兼CTO兼CFO&#xff0c;带领众子弟行走于云端计算&#xff0c;累计犒赏已达757157.09银两&#xff0c;江湖人称紫龙&#xff0c;就是众多阿里云大使中低调内敛的一位。其话不多&#xff0c;一个典型的技术男&#xff0c;但又热心钻研传播推广&#xff0c;不到…

Java-数组下标越界及小结

https://www.bilibili.com/video/BV12J41137hu?p54&spm_id_frompageDriver

如何给女朋友解释什么是撞库、脱库和洗库?

来源 | 漫话编程最近&#xff0c;安全圈又有一个大新闻&#xff0c;微博名为安全_云舒的微博用户在发文称&#xff1a;“很多人的手机号码泄露了&#xff0c;根据微博账号就能查到手机号……已经有人通过微博泄露查到我的手机号码&#xff0c;来加我微信了。”并且&#xff0c;…

OceanBase数据库实践入门——性能测试建议

概述 本文主要分享针对想压测OceanBase时需要了解的一些技术原理。这些建议可以帮助用户对OceanBase做一些调优&#xff0c;再结合测试程序快速找到适合业务的最佳性能。由于OceanBase自身参数很多、部署形态也比较灵活&#xff0c;这里并没有给出具体步骤。 数据库读写特点 …

Istio 在阿里云容器服务的部署及流量治理实践

目标 在阿里云容器服务 Kubernetes 集群上部署 Istio 服务网格实践灰度发布、故障注入、熔断等 Istio 流量管理特性 准备工作 安装和设置 kubectl 客户端&#xff0c;请参考不同的操作系统&#xff0c;如果已经安装请忽略&#xff1a; macOS curl -LO https://kubectl.oss-cn…

mysql创建操作用户

使用root用户创建一个新的数据库wiki 创建一个新的连接 由于新建的用户名下没有表&#xff0c;因此会抛出异常 就好了

Java-数组的使用

public class ArrayDemo03 {public static void main(String[] args) {int[] arrays {1,2,3,4,5};// JDK1.5&#xff0c; 没有下标&#xff0c;增强写法 // for (int array : arrays) { // System.out.println(array); // }printArray(arrays);Syste…

为何你的 SaaS 想法总是失败?没想清楚这 4 个原因可能会继续失败!

作者 | Elliot Bonneville译者 | 天道酬勤 责编 | 徐威龙封图| CSDN 下载于视觉中国最初&#xff0c;作者是准备进行一个”7 天 SaaS 挑战“的&#xff0c;但当他真正坐下来的时候就面临了第一个问题&#xff1a;他还没有决定要做什么。不过幸好的是&#xff0c;作者有一个完整…

重磅开源|AOP for Flutter开发利器——AspectD

问题背景 随着Flutter这一框架的快速发展&#xff0c;有越来越多的业务开始使用Flutter来重构或新建其产品。但在我们的实践过程中发现&#xff0c;一方面Flutter开发效率高&#xff0c;性能优异&#xff0c;跨平台表现好&#xff0c;另一方面Flutter也面临着插件&#xff0c;…

Vue-cli 3.X 构建工具零基础快速上手

文章目录一、环境准备1. 安装node2. 配置镜像二、安装Vue CLI2.1. 查看当前vuecli版本2.2. 安装最新版本2.3. 安装指定版本三、创建web项目3.1. 指定创建的项目名称3.2. 安装序列图3.3. 安装序列图简述一、环境准备 声明&#xff1a;命令均在在cmd窗口执行 1. 安装node 2. 配置…

分布式数据库选型——数据水平拆分方案

概述 水平拆分的概念随着分布式数据库的推广已为大部分人熟知。分库分表、异构索引、小表广播、这些功能几乎是产品功能需求标配。然而有些客户使用分布式数据库后的体验不尽如意。本文尝试从数据的角度总结分布式数据的复制&#xff08;replication&#xff09;和分区&#x…

从代码到 Docker、Kubernetes、Istio、Knative……,或许是时候重新思考从代码到云的编程了...

作者 | Lakmal Warusawithana译者 |弯月 责编 | 徐威龙封图| CSDN 下载于视觉中国早些时候&#xff0c;开发人员只需编写程序、构建&#xff0c;然后运行。如今&#xff0c;开发人员还需要考虑各种运行方式&#xff0c;作为可执行文件在机器上运行&#xff08;很有可能是虚拟机…

容器服务Windows Kubernetes使用阿里云日志服务来收集容器日志

目前&#xff0c;容器服务Windows Kubernetes支持将业务容器产生的stdout输出、日志文件同步到阿里云日志服务&#xff08;SLS&#xff09;进行统一管理。 支撑组件安装 在Windows Kubernetes集群安装界面勾选使用日志服务&#xff0c;集群会安装支持日志收集的必要组件logta…

Java-Arrays类

public class ArrayDemo06 {public static void main(String[] args) {int[] a {1,4,2,6,5,8,7};System.out.println(a); //hashCode [I1b6d3586// 打印数组元素 Arrays.toStringSystem.out.println(Arrays.toString(a)); // [1, 4, 2, 6, 5, 8, 7]// 自己写一个方法去打印…

看完这一篇,你就对 Spring Security 略窥门径了 | 原力计划

作者 | BoCong-Deng来源 | CSDN 博客&#xff0c;责编 | 夕颜头图 | CSDN 下载自东方 IC出品 | CSDN&#xff08;ID:CSDNnews&#xff09;写在前面开发Web应用&#xff0c;对页面的安全控制通常是必须的。比如&#xff1a;对于没有访问权限的用户需要转到登录表单页面。要实现访…