一次客户端与服务端性能监控“不对等”现象的排查过程- 踩坑总结集锦 18(一周一更)

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

问题背景

前几天遇到了一个非常有趣的“事故”案例,搜索调用下游rpc服务接口,监控报警超时,于是搜索系统的负责人“气势汹汹”的找到下游接口服务方问,你们接口是不是挂了,调用老是超时导致接口监控可用率低。下游服务端也是一脸懵,没有收到任何监控报警呀?于是打开监控,发现服务接口性能监控没有任何问题,双方监控不一致,于是开始了问题的排查和定位。

我先讲一下搜索构建索引的业务场景,方便我们去更好的理解出现的问题点。

搜索每天都会提前构建门店商品的索引,流程如下:

1、查询平台所有商家

2、开启多线程查询每一个商家下的所有门店列表、每个商家下的所有商品

3、组装门店商品信息,开启多线程

4、查询库存接口,过滤可售商品

5、开启多线程补全门店商品价格和促销

image.png

问题表象

在查询库存接口报错-错误如下:Waiting provider return response timeout ....

image.png

乍一看,肯定是库存接口超时导致的线程中断,而且通过异常堆栈可以看到,超时时间 2278ms,已经超过了设置的等待最大返回时间800ms,这就导致了搜索构建商品的时候库存数量缺失,中断索引构建。

问题排查

排查这种客户端、服务端接口性能监控不一致的总体思路前提,要了解一下各个环节点的耗时情况。

对于客户端来说,耗时主要由:建连时间 + 序列化时间 + 等待服务端处理时间组成;

对于服务端来说,耗时主要由:线程池等待时间 +服务处理时间 +结果序列化时间组成。

所以,对于我们一线开发,如果要对RPC耗时进行调优,最需要关注的,有客户端的路由寻址、序列化方式,有服务端的服务线程池等待、反序列化、服务端处理速率、结果序列化 这几块。

回到我们排查问题的思路上来,我们首先看下服务端的问题。

服务端:

1、当然,看到这个日志报错的异常堆栈后,第一时间肯定也会联想到,是不是库存接口挂了,有问题呢?于是联系到了库存的同学看下provider端的ump监控,结果发现,监控性能全都正常,而且通过性能监控可以排除都没有问题-如下图

(1)服务端线程池等待(通过接口性能可以直观看出来,如果有线程等待性能肯定变慢)-没问题

(2)结果序列化时间-没问题

(3)服务器处理时间-没问题

image.png

2、确认库存接口没问题后,接下来怀疑是不是库存返回的数据过大,等待服务端处理时间太长导致的线程中断,通过哪些指标可以确认呢?

(1)接口入参限制-最大300个

(2)库存缓存key-value非常小 几kb左右

(3)服务端服务器出流量 来看下是否有大流量返回-通过监控看也都正常,如下图

image.png

客户端

1、排除了服务端没有问题后,我们来看下客户端服务器,我们来看下客户端服务器业务线程耗时的环节

(1)建连时间

(2)序列化时间

(3)等待服务端处理时间

通过日志报错可以确定,目前出问题的是等待服务器处理时间线程超时,那么为什么超时呢?可能会存在如下几个原因

(1)cpu负载过高

(2)线程数太多,导致业务线程池打满走拒绝策略

(3)fullgc

先来看

(1)cpu负载情况,通过监控发现,cpu负载在可控范围内,并非100%负载,整体压力可控。

image.png

(2)业务线程池情况,通过监控可以看到线程数量很稳定,并没有出现飙升的现象

image.png

(3)最后怀疑是不是有fullgc,结果发现,构建某一个商家的时候,频繁的触发fullgc,构建其他商家没有问题,看了gc监控情况后,也印证了这个怀疑~!

image.png 每一次fullgc的平均耗时是20167ms,我们都了解fullgc会导致STW(Stop The World),在fullgc期间会挂起业务线程,gc后才会重新唤醒业务线程,最终导致了我们的jsf线程等待相应超时报错,给我们一个下游rpc接口有问题的错觉。

image.png

那么,问题来了,为什么会频繁fullgc呢?肯定是存在了大对象,导致每次gc的时候gc不掉。导致频繁的触发fullgc的阈值。

探寻导致频繁fullgc的大对象来源

一开始List<可售库存> 只保存可售的门店商品。

后来加了个判断,如果商家上架数量超过2w,那过滤条件就改成了List<可售库存+库存数量大于0>

出问题的商家恰好满足这些条件,而且这个商家下上架的sku 21W,散列到800个门店维度,轻松上亿。导致出现了大对象,然后频繁的触发fullgc

image.png

问题解决

1、调整合理的jvm参数,避免频繁fullgc(治标不治本,最好的方式还是优化业务代码)

2、修改业务代码,优化过滤逻辑,避免大对象产生gc不掉

总结

1、如果出现客户端、服务端监控不对等的情况出现 一定要有一个清晰的排查思路,要知道哪些环节点会导致监控不对等的情况

2、针对流程进行逐项排查,发现问题点

3、这种就属于比较麻烦的问题,因为通过横向扩容是无法解决问题的,我们在开发过程中,一定要进行充分的压测,尽量提前避免这种问题产生

猜你喜欢

转载自juejin.im/post/7110371866233012238
今日推荐