性能文章>服务响应时间飙升问题排查记>

服务响应时间飙升问题排查记原创

1年前
7051012

这个case大概发生在一年前,现在拿出来给大家做个分享。

现象

下游有server服务上线一台机器,导致上游服务调用下游服务时间升高,young gc 增多,cpu利用率增高,但是从下游server服务看各项指标都很正常。

image.png

从client看调用下游服务监控

image.png
young gc监控

问题排查过程

因为是cpu飙升很多,于是就在监控系统cat上看了一下出问题时候的堆栈信息,关键信息如下:

image.png

看堆栈信息应该是加载类的时候未加载到,询问下游服务负责人是否在RPC接口中增加新的返回字段,被告知并没有。

再次查看服务本身,发现服务使用到了pigeon和thrift两种RPC框架,使用pigeon框架的服务接口都飙升了,而使用thrift框架的服务接口却是正常了。这样说明服务延迟上升不是由于cpu升高、young gc次数增多导致的。应该是其他原因导致的。cpu升高、young gc次数和服务响应时间升高都是结果。

作为RPC框架,他们基本上有类似的信息流向:

image.png

在业务逻辑监控下,发现业务逻辑的响应时间都是正常的,和业务逻辑没有关系。那么pigeon的接口飙升的原因基本上只能在I/O线程里。

查看pigeon这块源码发现,发现调用下游的服务都是共用了一个I/O线程,并且在I/O线程处理逻辑如下:

image.png

于是还是应该把着重点放在反序列化上,在反序列化方法上加上监控,准备上线时,却发现线上tomcat日志有以下错误:

image.png

很明显在序列化查找类的时候,找不到该类。再次联系下游服务是不是添加了ShopPic这个对象,他们再次查看代码确实在返回对象中添加了List<ShopPic> 对象类型。

让他们提供新的jar版本,服务升级后问题解决。

原理分析

因为pigeon服务在从下游拿到数据之后,需要进行反序列化,使用的反序列化方式是hession。hession在反序列化时,需要加载class,若class加载到了会缓存下来,加载不到会每次都会尝试再次加载。而添加的对象刚好又是list,里面的每个对象都会走“加载类,未找到,输出log”模式。而这一过程本身是比较耗cpu和时间的,并且生成不少临时变量。消耗时间会导致pigeon的I/O线程阻塞,进而导致其他pigeon服务延迟也升高。

总结

通常我们在做问题排查的时候,一般要先把所有的异常现象都给列举出来。然后查看这些现象本身是否有因果关系。确定某些现象有因果关系,那么就要把查看重点放在因。列举出独立的异常现象之后,可以先从比较容易着手的异常现象排查,有时候一个异常现象被找到解决,可能其他所有异常现象都会解决。

比如本例有3个异常表现:cpu升高、young gc次数增多、服务超时增多。cpu升高可能会导致服务超时增多,但是进程内所有的服务都应该受影响,不只是pigeon服务,所以排除这两者之间的因果关系。young gc次数增多会导致cpu略微升高,但是本例中不能就因此确定cpu升高就是young gc导致的。在本例中的3个异常表现中,cpu升高最好排查、服务超时增多次之、young gc次数增多最难排查。所以问题排查就应该按照先排查cpu问题、再排查服务超时问题、最后再是young gc次数增多。

请先登录,再评论

暂无回复,快来写下第一个回复吧~

为你推荐

字符串字面量长度是有限制的
前言 偶然在一次单元测试中写了一个非常长的字符串字面量。 正文 在一次单元测试中,我写了一个很长的字符串字面量,大概10万个字符左右,编译时,编译器给出了异常告警 `java: constant
多次字符串相加一定要用StringBuilder而不用-吗?
今天在写一个读取Java class File并进行分析的Demo时,偶然发现了下面这个场景(基于oracle jdk 1.8.0_144): ``` package test; public c
如何通过反射获得方法的真实参数名(以及扩展研究)
前段时间,在做一个小的工程时,遇到了需要通过反射获得方法真实参数名的场景,在这里我遇到了一些小小的问题,后来在部门老大的指导下,我解决了这个问题。通过解决这个问题,附带着我了解到了很多新的知识,我觉得
JVM源码分析之String.intern()导致的YGC不断变长
概述之所以想写这篇文章,是因为YGC过程对我们来说太过于黑盒,如果对YGC过程不是很熟悉,这类问题基本很难定位,我们就算开了GC日志,也最多能看到类似下面的日志`[GC (Allocation Fai
高吞吐、低延迟 Java 应用的 GC 优化实践
本篇原文作者是 LinkedIn 的 Swapnil Ghike,这篇文章讲述了 LinkedIn 的 Feed 产品的 GC 优化过程,虽然文章写作于 April 8, 2014,但其中的很多内容和
「每日五分钟,玩转 JVM」:久识你名,初居我心
聊聊 JVMJVM,一个熟悉又陌生的名词,从认识Java的第一天起,我们就会听到这个名字,在参加工作的前一两年,面试的时候还会经常被问到JDK,JRE,JVM这三者的区别。JVM可以说和我们是老朋友了
据说99.99%的人都会答错的类加载的问题
概述首先还是把问题抛给大家,这个问题也是我厂同学在做一个性能分析产品的时候碰到的一个问题。 同一个类加载器对象是否可以加载同一个类文件多次并且得到多个Class对象而都可以被java层使用吗请仔细注意
Java多线程——并发测试
编写并发程序时候,可以采取和串行程序相同的编程方式。唯一的难点在于,并发程序存在不确定性,这种不确定性会令程序出错的地方远比串行程序多,出现的方式也没有固定规则。那么如何在测试中,尽可能的暴露出这些问