容器内微服务OOM问题排查及解决

背景

问题现象:测试环境,有一个功能的所有接口请求超时,查看微服务下的日志,发现OOM了

问题环境:Kubernetes环境,微服务部署在pod的容器中

 

问题排查

1、环境出现问题时,首先查看服务日志,发现OOM了:

2、发生OOM时,会在容器内自动生成一个hprof快照文件,立马拷贝到宿主机(pod重启后会丢失),然后再拷贝到本机:

3、在本机使用JProfiler打开快照文件,首先查看堆内存中类的大小排序:

 4、看到了一个熟悉的实体类,初步怀疑有可能是这个实体类占用内存太多导致的。点开"最大对象",会发现最大的两个分别是ArrayList和Mongo对象:

  5、选定对象后,查看两个大对象中的内容,分别为:

ArrayList对象:

 Mongo对象:

 

 6、通过以上信息,基本可以判断是查询mongo中的app_ids_info_rule_details表时,返回了大量的SysRuleDetailDO对象导致的

7、将这两个对象在图表中显示,可以看到是哪一行代码进行的mongo查询:

8、找到对应代码:

 9、找相关同学了解,发现出现OOM问题前,有大量的客户端多次调用查询系统规则详情的接口,这样就会在极短时间内大量的查询mongo库的操作,导致内存中有大量的该对象

 

解决方案

通过了解发现:

  • 每次查询规则数据后,会在内存中进行大量的计算,最终得到一个很简单的数据结构然后返回给客户端。
  • 每次导入规则数据后,服务端会收到规则变化的回调消息

对于上面的两点,可以发现很好的优化点:

  • 额外增加一张表,当收到规则变化的回调消息时,提前计算后需要返回给客户端的数据,并保存到数据库
  • 为了进一步提升性能,还可以加一个本地缓存
    • 收到规则回调消息后,先写入缓存,再入库
    • 客户端查询规则,先查询缓存,没有命中再查库,然后再刷新缓存

 

posted @ 2023-03-10 09:41  仅此而已-远方  阅读(521)  评论(0编辑  收藏  举报