记录一次线上服务接口偶现超时问题定位(内存问题)

2019-02-26  本文已影响0人  Yves_Chen

发现问题:上层服务A任务失败触发告警,排查是因为调用服务B时接口偶现time out。
登录服务B定位:
首先确定网络无异常。
然后查看了下上层服务A报超时的请求,服务B确实产生了访问日志,怀疑是服务B内部问题。
Top查看了下CPU使用情况,发现CPU使用率较低,但是每隔几秒会跑到300%以上(4核),业务上没有这种间隔几秒执行的后台任务,怀疑是GC异常了。
用jstat -gc *** 5000 10查看GC情况,吓了一跳。每隔5秒打印一次GC,FGC在不断增长,几乎每5秒FGC要增长1~2次,每次花费2秒。(公司内网无法上传图片,改文字描述。。。)
用jmap -histo:live看了下堆内的对象占用情况,发现业务对象占用很低,绝大部分是hibernate的内部对象。
用jmap将堆导出,然后重启了服务,观察服务暂时正常,然后用MAT打开堆文件分析内存泄漏情况:
One instance of "org.hibernate.internal.SessionFactoryImpl" loaded by "org.apache.catalina.loader.WebappClassLoader @ 0x70012b8a0" occupies 2,683,463,880 (95.68%) bytes. The memory is accumulated in one instance of "org.hibernate.internal.util.collections.BoundedConcurrentHashMap$Segment[]" loaded by "org.apache.catalina.loader.WebappClassLoader @ 0x70012b8a0".
发现SessionFactoryImpl下整个引用链占用了对95.68%的空间,往下跟踪了一下,发现空间是被org.hibernate.engine.query.spi.QueryPlanCache占用。
查了下资料,QueryPlanCache占用多大,它基本上归结为IN子句中具有可变数量的值,而Hibernate试图缓存这些查询计划。如: select t from Thing t where t.id in (?)。Hibernate缓存这些解析的HQL查询。如果in子句后面跟不同数量或数值,都会增加一条缓存。业务上确实存在in后面带了大量子句的场景。
先配置
<property
name="hibernate.query.plan_cache_max_size"
value="2048"
/>
<property
name="hibernate.query.plan_parameter_metadata_max_size"
value="128"
/>
暂时规避问题。
PS:奇怪为什么这里做缓存不用WeakReference或SoftReference?

上一篇下一篇

猜你喜欢

热点阅读