一、问题描述
从用户反馈服务崩溃开始,查找问题所在。
首先查看了服务的日志情况,没有什么太大的异常,主要都是zookeeper连接的异常。由于我们的服务使用docker部署,进入容器想查看一下GC情况,结果发现heapdump.hprof
已经存在(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/heapdump.hprof)不用看了,服务已经OOM了,查看ELK的日志也确实OOM了。
二、解决思路
既然已经内存溢出了,肯定要进行堆内存分析。先将heapdump.hprof
文件从容器内部拷贝到本地。除了使用(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/heapdump.hprof)以外也可以直接使用如下命令又dump。
jmap -dump:live,format=b,file=heap.bin <pid>
使用的Eclipse Memory Analyzer
工具进行如下分析,请到官方下载地址自行下载安装。
打开heap.bin
文件
文件过大的话,可能需要等待一些时间,然后选择Leak Suspects Report
,点击Finish完成
点击Leak Suspects
,查看可能存在的问题。
观察到有一个894.1MB的Suspect,问题出现在它的身上。
往下滑动,点击Details
,查看详细信息。
可以看到是QueryPlanCache
导致的,询问开发后确实有很多in
语句(基本上可以归结为在IN子句中具有可变数量的值,而Hibernate尝试缓存那些查询计划
)
通过搜索大量关于QueryPlanCache的文档,最终采用如下方案解决:
spring:
jpa:
properties:
hibernate:
query:
plan_cache_max_size: 64
plan_parameter_metadata_max_size: 32
参考文档:https://stackoverflow.com/questions/31557076/spring-hibernate-query-plan-cache-memory-usage