zoukankan      html  css  js  c++  java
  • 性能测试案例:一个频繁fgc问题

    今天分享一个频繁fgc的问题,现象是接口响应时间太长了,达到了好几秒,远远高于预期的1秒。

    01

    监控

    xshell连接到应用服务器,服务器负载高,且cpu使用率也偏高

    使用jstat看了下gc的情况,fgc很频繁,老年代满了(下图的O列)

    打开JvisualVM,双击对应的应用进程,然后进入Monitor,可以看到堆内存GC频繁。然后进入 Visual GC查看,发现堆内存Full GC非常频繁

    根据下面gc日志,Full GC Old区回收的内存很少

    现在情况就非常明显了,就是内存中有大量GC不掉的对象。

    02

    分析定位

    下面我们看看heap里面到底是些什么东西。切换到monitor,点击heap dump生成dump文件,然后把dump文件拷贝到本机进行分析。

    分析dump文件,点击class,根据size排序,找到比较大且比较熟悉的实例,下面对红框中两个class进行分析。

    sacToNoticeConfirmRequest这个class是业务接口,但是现在应用程序并没有请求sacToNoticeConfirm这个接口,为啥这个class会有这么多对象呢?

    先分析其他对象,ConstraintViolationimpl这个class是dubboRPC请求对参数进行验证时需要的类,看看这个类的实例都是些什么内容:

    看了多个实例后发现ConstraintViolationimpl这个class的实例对象都是因为RPC参数校验不通过生成的对象。我们在sacToNoticeConfirmRequest这个类里面使用了javax.validation这个包的注解,如果sacToNoticeConfirmRequest请求参数在RPC调用时参数校验不通过就会产生大量的ConstraintViolationimpl实例。我们继续分析sacToNoticeConfirmRequest这个class的实例:

    看了多个实例后,终于知道这些GC不掉的内存是哪里来的了。猜想应该是压测的时候没有填写参数的原因(其实是可以不填参数就请求接口),而我们的接口用了Dubbo的参数校验这个特性,那么在Dubbo框架层就会校验这些参数,校验不通过就会产生大量的ConstraintViolationimpl实例(这些实例又引用了很多HashMap$Node实例)。填写参数压测,就没出现频繁fgc的情况。

    现在找到问题了,就是因为使用Dubbo参数验证这个特性,在大多数请求参数校验不通过的情况下就会出现大量对象GC不掉,导致频繁FULL GC,最终导致响应时间很慢的情况。

    03

    调优总结

    至于为什么在这种情况下大量的对象GC不掉,猜测这个可能是Dubbo参数校验的bug,所以建议不要使用Dubbo的参数校验,可以使用Dubbo的本地存根(stub)这个特性来替代Dubbo的参数校验。

    Dubbo的本地存根:在远程调用服务提供者的实现之前,提供方有时候想在客户端也执行部分逻辑,如果需要做一些参数验证、判断等,满足要求再调用服务提供者的远程服务,则我们可以通过编写一个本地存根来实现这种功能。

    dubbo本地存根的原理,大家可以网上查询了解。

  • 相关阅读:
    spring cloud config 属性加解密
    IntelliJ IDEA 快捷键
    SQL Server 2012 安装图解教程(附sql2012下载地址)
    spring cloud 启动报错-must be declared as an @AliasFor [serviceId], not [name].
    MySQL主从复制配置
    恢复MySQL数据库删除的数据
    java.lang.IllegalStateException: No instances available for localhost
    蜘蛛牌 (DFS)
    加油站问题 (优先队列)
    堆的操作的复杂度
  • 原文地址:https://www.cnblogs.com/mycftest/p/13502562.html
Copyright © 2011-2022 走看看