如何使用Profiler定位OOM问题
背景
服务所在容器频繁重启,通过自监控发现重启前fullgc次数会突增(约每分钟20次)。
使用Profiler定位OOM问题
- 登录管理控制台。
- 单击左侧,选择“管理与监管 > 应用性能管理 APM”,进入APM服务页面。
- 在左侧导航栏选择“应用监控 > 指标”。
- 在界面左侧树单击待查看Profiler性能分析环境后的。
- 单击“Profiler性能分析”,切换至Profiler性能分析页签。
- 单击“性能分析”,进入性能分析页面。
- 选择类型:Memory,范围:All Code,聚合维度:Method,发现有两个方法占用了较多内存。
- 单击“方法路径”列,对应的方法名找到该方法的调用栈,向上找到调用此方法的业务代码。
- 定位到业务代码块,该代码使用了一个缓存来存放每个instance的信息。通过自监控查看该sql的调用,发现每分钟会调10万次,进一步证实是缓存失效了。
当查询instance信息时,会先从缓存查,如果查不到再从mysql查。instance信息查到之后存入缓存,防止频繁访问数据库。
- 检查代码发现缓存的key是一个类,该类没有重写equals和hashCode方法。因此,导致缓存通过key去获取value时,会根据key的地址来判断该key是否在缓存中存在。而每次传参进来的key地址都不一样,所以从缓存中查找失败,只能从mysql查找,然后又不断往缓存中存,最终导致OOM问题。
解决方案
给作为key的类重写equals和hashCode方法。该类有个uuid属性,不同instance的uuid不一样,因此可以用uuid来判断两个instance是否相同。