解Bug之路-记一次线上请求偶尔变慢的排查

前言

最近解决了个比较棘手的问题,由于排查过程挺有意思,于是就以此为素材写出了本篇文章。

Bug现场

这是一个偶发的性能问题。在每天几百万比交易请求中,平均耗时大约为300ms,但总有那么100多笔会超过1s,让我们业务耗时监控的99.99线变得很尴尬。如下图所示:



为了精益求精,更为了消除这个尴尬的指标,笔者开始探寻起这100多慢请求笔的原因。

先找一笔看看

由于笔者写的框架预留了traceId,所以找到这笔请求的整个调用的链路还是非常简单的。

而且通过框架中的拦截器在性能日志中算出了每一笔请求的耗时。这样,非常便于分析链路倒是是在哪边耗时了。性能日志中的某个例子如下图所示:

2020-09-01 15:06:59.010 [abcdefg,A->B,Dubbo-thread-1,ipA->ipB] B.facade,cost 10 ms

拉出来一整条调用链路后,发现最前面的B系统调用C系统就比较慢。后面链路还有几个调用慢的,那先不管三七二十一,先分析B调用C系统把。



我们从监控系统看出来正常的B系统调用C系统平均耗时只有20ms,这次的耗时增长了10倍!



正常思路,那当然是C系统有问题么,毕竟慢了10倍!去C系统的性能日志里面看看,

2020-09-01 15:06:59.210 [abcdefg,B->C,Dubbo-thread-1,ipB->ipC] C.facade,cost 20 ms

啪啪啪打脸,竟然只有20ms,和平均耗时差不多。难道问题在网络上?B到C之间由于丢包重传所以到了200ms?

甩给网络?

由于笔者对TCP协议还是比较了解的,tcp第一次丢包重传是200ms,那么加上C处理的时间20ms,即220ms必须得大于200ms。而由于Nagle和DelayAck造成的tcp延迟也仅仅是40ms,两者相加60ms远远小于200ms,所以这个200ms是丢包或者DelayAck的概率不大。



本着万一呢的态度,毕竟下绝对的判断往往会被打脸,看了下我们的监控系统,发现当时流量距离网卡容量只有1/10左右,距离打满网卡还有非常远的距离。



注意,这个监控的是由KVM虚拟机虚拟出来的网卡。

看了这个流量,笔者感觉网络上问题的概率不大。

GC了?

笔者第二个想到的是GC了,但是观察了B和C的当时时刻的GC日志,非常正常,没有FullGC,youngGC也在毫秒级,完全不会有200ms这么长。TCP重传+双方都youngGC?这个也太巧了点吧,也不是不可用。不过详细的计算了时间点,并纳入了双方机器的时钟误差后,发现基本不可能。

再看看其它几笔

尽然这个问题每天有100多笔(当然了,也不排除其中混杂了其它不同的问题),那么就试试看看其它几笔,有没有什么共性。这一看,发现个奇怪的现象,就是有时候是A调用B慢,有时候是B调用C慢,还有时候是E调用F慢。他们唯一的共性就是耗时变长了,但是这个耗时增加的比例有5倍的,有10倍的,完全没有规律可循。



这不禁让笔者陷入了沉思。

寻找突破点

既然通用规律只有变慢,暂时无法进一步挖掘。那么还是去B系统上去看看情况吧,去对应B系统上故意不用grep而是用less看了下,上下扫了两眼。突然发现,貌似紧邻着的几条请求都很慢,而且是无差别变慢!也就是说B系统调用任何系统在这个时间点都有好几倍甚至十几倍的耗时!



终于找到了一个突破点,B系统本身或者其所属的环境应该有问题!于是笔者用awk统计了下

B系统这个小时内每分钟的平均调用时长,用了下面这条命令:

cat 性能日志 | grep '时间点 | awk -F ' ' '{print $2, $5}' |.......| awk -F ' ' '{sum[$1]+=$3;count[$1]+=1}END{for(i in sum) {print i,sum[i]/count[i]}}'

发现

15:00 20
15:01 21
15:02 15
15:03 30
.......
15:06 172.4
15:07 252.4
15:08 181.4
15:10 20
15:10 21
15:10 22

在15:06-15:08这三分钟之内,调用时间会暴涨!但奇怪的是B系统明明有几十台机器,只有这一台在这个时间段内会暴涨。难道这个时间有定时任务?笔者搜索了下B系统昨天的日志,发现在同样的时间段内,还是暴涨了!再接着搜索其它调用慢的,例如E->F,发现他们也在15:06-15:08报错!于是笔者,一横心,直接用awk算出了所有系统间调用慢机器白天内的所有分钟平均耗时(晚上的流量小不计入内),发现:



所有调用慢的机器,都非常巧的在每个小时06-08分钟之内调用慢。再观察下慢的请求,发现他们也全部是分布在不同小时的06-08分时间段内!

定时任务?

第一反应是有定时任务,查了下所有调用机器的crontab没有问题。问了下对应的开发有没有调度,没有调度,而且那个时间段由于耗时的原因,每秒请求数反而变小了。翻了下机器监控,也都挺正常。思维陷入了僵局,突然笔者灵光一闪,我们的应用全部是在KVM虚拟机上,会不会是宿主机出了问题。于是联系了下SA,看看这些机器的宿主机是个什么情况。

每个变慢的机器的宿主机都有Redis!

这一看就发现规律了,原来变慢的机器上都和Redis共宿主机!



登陆上对应的Redis服务器,发现CPU果然在那个时间点有尖峰。而这点尖峰对整个宿主机的CPU毫无影响(毕竟宿主机有64个核)。crontab -l 一下,果然有定时任务,脚本名为Backup!它起始时间点就是从06分开始往GlusterFS盘进行备份,从06分开始CPU使用率开始上升=>07分达到顶峰=>08分降下来,和耗时曲线完全一致!



原来Redis往Gluster盘备份占据了大量的IO操作,所以导致宿主机上的其它应用做IO操作时会变得很慢,进而导致但凡是这个备份时间内系统间调用的平均耗时都会暴涨接近10倍,最终导致了高耗时的请求。

为什么调用请求超时1s的概率这么低

由于我们线上每个应用都有几十台机器,而基本每次调用只有几十毫秒。所以只有这个请求连续落到三个甚至多个和Redis共宿主机的系统里面才会导致请求超过1s,这样才能被我们的统计脚本监测到,而那些大量的正常请求完全拉平了平均值。

解决方案

我们将线上实时链路的系统从对应有Redis的宿主机中迁移出来,再也没有那个尴尬的1s了。

总结

在遇到问题,并且思路陷入僵局时,可以通过一些脚本工具,例如grep以及awk或者其它一些工具对众多日志进行分析,不停的去寻找规律,从无序中找到有序,往往能够产生意想不到的效果!

欢迎大家加我公众号,里面有各种干货,还有大礼包相送哦!

解Bug之路-记一次线上请求偶尔变慢的排查的更多相关文章

  1. 解Bug之路-记一次中间件导致的慢SQL排查过程

    解Bug之路-记一次中间件导致的慢SQL排查过程 前言 最近发现线上出现一个奇葩的问题,这问题让笔者定位了好长时间,期间排查问题的过程还是挺有意思的,正好博客也好久不更新了,就以此为素材写出了本篇文章 ...

  2. 解Bug之路-记一次存储故障的排查过程

    解Bug之路-记一次存储故障的排查过程 高可用真是一丝细节都不得马虎.平时跑的好好的系统,在相应硬件出现故障时就会引发出潜在的Bug.偏偏这些故障在应用层的表现稀奇古怪,很难让人联想到是硬件出了问题, ...

  3. 解Bug之路-记一次JVM堆外内存泄露Bug的查找

    解Bug之路-记一次JVM堆外内存泄露Bug的查找 前言 JVM的堆外内存泄露的定位一直是个比较棘手的问题.此次的Bug查找从堆内内存的泄露反推出堆外内存,同时对物理内存的使用做了定量的分析,从而实锤 ...

  4. 解Bug之路-记一次对端机器宕机后的tcp行为

    解Bug之路-记一次对端机器宕机后的tcp行为 前言 机器一般过质保之后,就会因为各种各样的问题而宕机.而这一次的宕机,让笔者观察到了平常观察不到的tcp在对端宕机情况下的行为.经过详细跟踪分析原因之 ...

  5. 解Bug之路-记一次调用外网服务概率性失败问题的排查

    前言 和外部联调一直是令人困扰的问题,尤其是一些基础环境配置导致的问题.笔者在一次偶然情况下解决了一个调用外网服务概率性失败的问题.在此将排查过程发出来,希望读者遇到此问题的时候,能够知道如何入手. ...

  6. 解Bug之路-TCP粘包Bug

    解Bug之路-TCP粘包Bug - 无毁的湖光-Al的个人空间 - 开源中国 https://my.oschina.net/alchemystar/blog/880659 解Bug之路-TCP粘包Bu ...

  7. 解Bug之路-Nginx 502 Bad Gateway

    解Bug之路-Nginx 502 Bad Gateway 前言 事实证明,读过Linux内核源码确实有很大的好处,尤其在处理问题的时刻.当你看到报错的那一瞬间,就能把现象/原因/以及解决方案一股脑的在 ...

  8. 解Bug之路-串包Bug

    解Bug之路-串包Bug 笔者很热衷于解决Bug,同时比较擅长(网络/协议)部分,所以经常被唤去解决一些网络IO方面的Bug.现在就挑一个案例出来,写出分析思路,以飨读者,希望读者在以后的工作中能够少 ...

  9. 解Bug之路-NAT引发的性能瓶颈

    解Bug之路-NAT引发的性能瓶颈 笔者最近解决了一个非常曲折的问题,从抓包开始一路排查到不同内核版本间的细微差异,最后才完美解释了所有的现象.在这里将整个过程写成博文记录下来,希望能够对读者有所帮助 ...

随机推荐

  1. 目标检测中的IOU和CIOU原理讲解以及应用(附测试代码)

    上期讲解了目标检测中的三种数据增强的方法,这期我们讲讲目标检测中用来评估对象检测算法的IOU和CIOU的原理应用以及代码实现. 交并比IOU(Intersection over union) 在目标检 ...

  2. python应用 曲线拟合 02

    前情提要 CsI 闪烁体晶体+PD+前放输出信号满足: $U(t) = \frac{N_f\tau_p}{\tau_p-\tau_f} \left[ e^{-\frac{t}{\tau_p}}-e^{ ...

  3. Linux通过命令行将英文改成中文

    1.首先查看当前系统是否有中文语言包 locale -a 如果没有zh_CN.utf8,就需要下载中文语言包,否则,如果有中文语言包,跳过第二步. 2.安装中文语言包 Ubuntu: sudo apt ...

  4. Linux:正则表达式2

    基础正则表达式 ^ : 以xx开头 $ :以xx结尾 ^$ :代表空行 .   任意一个字符 \   :转义符号,让有着特殊意义的字符可被使用 * :重复0个或多个前面的字符,例如 a* 2表示a后面 ...

  5. 编程体系结构(03):Java集合容器

    本文源码:GitHub·点这里 || GitEE·点这里 一.集合容器简介 集合容器是Java开发中最基础API模块,通常用来存储运行时动态创建的元素,基本特点如下: 泛型特点,存储任意类型对象: 动 ...

  6. appium的基本环境配置

    1.先安装jdk1.7或jdk1.8之后,并配置好环境变量 2.安装Android SDK(安卓软件开发包),测试Android手机必然要安装Android SDK,例如android-sdk_r24 ...

  7. Spring Batch远程分区的本地Jar包模式

    1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Spring相关文章:Springboot-Cloud Spring Batch远程分区对于大量数据的处理非常擅长,它的实现 ...

  8. [LeetCode]603. 连续空余座位(Mysql、自连接)

    题目 几个朋友来到电影院的售票处,准备预约连续空余座位. 你能利用表 cinema ,帮他们写一个查询语句,获取所有空余座位,并将它们按照 seat_id 排序后返回吗? | seat_id | fr ...

  9. Linux入门到实战

    关注公众号 cxytester 获取第一手资讯. 1. 全是干货-Linux命令大全 1.1 线上查询及帮助(1个) help 1.2 文件目录及操作(12个) ls tree pwd mkdir r ...

  10. Spring Cloud各组件学习

    Spring-Cloud 介绍 SpringCloud各个组件详解,因为SpringCloud部分组件停止更新,故本项目包含原SpringCloud(基于SpringCloud H版和SpringBo ...