一、概述
1.1、前言
监控打点也能导致PRC调用超时?那么不是扯蛋么?不要捉急,相信看完本篇文章就能得到答案了。建议阅读时长5min。
1.2、背景
某个酷似夏天的冬天,发现资金平台调用流动性平台批量查询资金包余额接口(BatchGetBalanceByPackageNo)有大量的RPC调用超时失败告警,最近半个月上游视角SLA一度降到99.854%,而该链路属于L0链路,目标SLA是99.995%,所以需要排查处理以确保SLA满足要求。

二、你的收获
通过本文你能收获什么?

三、排查思路
3.1、查看错误日志
发现RPC错误,那还不简单,通常思路当然是先拿到logid然后查看看下错误日志。

发现是超时,那就好排查了,于是找到下游查看是否是服务提供方处理耗时过高。
3.2、服务端耗时分析
既然是RPC超时,那么很有可能是下游server端处理花费的时间过长导致,于是找到一条超时记录的logid,一般接口请求和响应都有打印日志的,通过分析,对应的下游服务耗时从接受到请求到响应耗时在10ms以内(抱歉这里没有截图,日志过期了,所以总结还是要尽早)。那么到底是什么问题导致请求超时超时呢?
3.3、调整超时时间
分析发现当前client段配置的超时时间是100ms,考虑是不是因为偶发性导致超时的,因为上游视角P99在10ms以内(图3.3.1),于是调整超时时间到200ms。

图3.3.1

图3.3.2
调整超时时间到200ms后,通过图3.3.2发现超时基本没有任何变化,所以排除偶发性超时问题。
3.4、RPC耗时拆解分析
以上基本都是一些猜测,要找到原因还是需要查看一次RPC时间都消耗在哪里。这里可以通过argos已有能力排查。
入口:观察诊断>APM>logid检索>链路拓扑>底层调用
阶段说明:PerfT Event 说明

通过分析链路图发现client段在等待server端响应的过程中超时了。在3.2步中分析server段实际处理耗时在10ms耗时以内,但是client端却等待超时了?那么这到底是什么问题,怀疑是否是网络问题,仔细思考又排除了,这个问题发生的太频繁了,如果是网络问题那么为什么其他接口没有问题,问题到这里更加朴素迷离了。
3.5、使用argos诊断工具分析
通过找搜索argos提供了一个很好用的工具。
找到argos小助手,使用命令发起分析(cds_key在client端错误日志中可以找到):

查看分析结果:cloud.bytedance.net/argos/aaas/...

分析结论命中两个问题:1、server端单实例问题。2、server端CPU受限。

- 优先按照server端单实例问题处理,迁移了命中的单实例服务后发现超时问题依然存在,且发现错误分布的服务比较分散,因此排除单实例问题。
- 考虑是CPU受限的问题。基于上面分析排除了server端单点问题,基于监控来看那么很可能是CPU受限的问题了。
3.6、CPU受限分析
根据上面监控发现CPU受限非常频繁,但是CPU使用率却比较低,那么到底是什么原因呢?于是拉了oncall沟通,没有提供太多有用的信息,oncall反馈这个一般是业务的问题,只能业务自己来排查,建议扩容服务数量或者扩容CPU核心数。既然oncall无法提供有用信息,所以思考CPU受限一般是什么情况下发生的呢?找了下文档,果然找到了。

那么既然分配给POD的CPU时间使用完了为什么CPU使用率还这么低,分析后发现CPU使用率打点是30秒的粒度,如果30秒以内瞬间飙高监控是反应不出来的,也就没有CPU使用过高的告警。于是分析到现在初步可以确定是因为CPU受限导致服务端返回的时候POD没有CPU时间可用导致进程被夯住了。
3.6.1、server端服务数扩容
既然CPU受限首先想到的就是服务数扩容,让更多的服务来处理请求,那么单个服务处理的请求就会降低,同时通过分析发现server端服务数量是client端的1/2且是client端上游的1/4,于是把server端服务两个机房的服务,从30扩容到80(基本和上游服务对齐,但是只有client端的上游的1/2)。

图3.6.1.1

图3.6.1.2

图3.6.1.3
从图3.6.1.2可以看出来扩容后CPU受限没有下降反而在后续几天的时间还有上升的趋势,从图3.6.1.3分析超时错误数量也基本没有变化,所以基本排除不是因为流量的问题,且和机器数多少相关性不大。
3.6.2、server端扩容CPU核心数
既然CPU受限,扩容后又没有效果,所以考虑是否把POD的CPU核心数扩大,给POD分配更多的CPU时间就能解决问题?于是把server端的POD的CPU核心数从4库容到8

图3.6.2.1

图3.6.2.2

图3.6.2.3
从图3.6.2.2可以看出来扩容后CPU受限的次数有了明显的下降,通过图3.6.2.3分析超时错误数量整体上也有了一些下降(错误没有那么频繁了),但是CPU受限还是存在只是降低了一些但是没有消除,说明CPU核心数扩容有一定的作用,但是没有找到根本原因。
3.6.3、火焰图之(CPU耗时分析)
上面的CPU核心数扩容只是缓解了问题并没有找到真正的原因。要想找到根因那么只能分析POD分配的CPU时间到底花到哪里去了。经过内部文档查询可以通过火焰图来分析POD的CPU时间消耗分布。
采样入口:cloud.bytedance.net/lidar/servi...
火焰图分析:Pprof 原理和火焰图使用方法
本次分析火焰图地址:lidar.bytedance.net/api/v1/ppro...

图3.6.3.1
监控打点封禁查询:cloud.bytedance.net/metrics/sel...

图3.6.3.2

图3.6.3.3
从上面3.6.3.1的CPU火焰图分析很明显可以发现CPU时间71.55%花费在监控打点上,且发现是两个定时任务发起的打点,同时发现打点因为数量过多(每天监控打点数=24*3600*100*4*180=62亿)导致被封禁,奇怪的是打点数量超过阈值被封禁没有任何报错或者告警(这个有点坑)。
3.7、业务改造
经过上面分析确认是监控打点的问题,分析发现这个监控打点是之前切流遗留的代码,当前已经无用,可以下线,于是进行代码下线。

图3.7.1

图3.7.2

图3.7.3
代码下线后,根据上图图3.7.1、图3.7.2以及图3.7.3分析server端的CPU受限降到0、client端的超时数量降到0,client端视角的SLA上升到100%,于是可以确定接口超时的根本原因:因为打点过快占用了大量的CPU时间导致接口处理后返回的时候分配给server端POD的CPU时间使用完了导致夯住所致。
四、总结
本次问题排查花费了不少时间,走了一些弯路,非常意外,没想到最后发现是监控打点导致的问题,本次问题总结如下:
- 监控打点要注意打点的维度以及数量,不要超过监控打点封禁的阈值,否则可能占用CPU过高影响服务。
- RPC接口超时分析不能局限于单个因素,可能的因素很多网络、单实例、服务端处理性能(慢sql、未命中缓存等)、超时配置不合理、CPU受限等,需要根据现象逐一排除,直到找到根因并解决。
- 合理使用排除工具如logid链路分析、argos诊断工具、火焰图等,有利于提高线上问题排查效率。
以上是我排查问题的一些思路,期望能够给大家带来一些帮助。
参考
内推活水
财金消费金融团队,欢迎内推活水。