记一次线上服务假死问题(MongoDB超时和OOM两个坑)

事件的背景是:一个老系统,功能模块很多,包含两个团队的职责(最开始只有一个团队),所以要将这个系统拆分成两个服务,各自团队负责自己的服务,由于业务影响,这次上线只能在23点后通宵进行。
问题一:ECS自建Mongo数据表数据量大,没有建索引,导致查询巨慢,CPU打满。
问题发生在第二天下午,提供给APP的接口响应变慢,后来应用假死(CPU、内存、带宽都检查过没有异常)。因为接口逻辑并不复杂,推断主要耗时就在从Mongo获取上,看Mongo的那台服务器,发现CPU已经打满了,然后就分析Mongo正在执行什么任务,可以参考这篇文章:https://www.cnblogs.com/operationhome/p/10728654.html
最终就发现,慢查询的集合全都只有id索引,业务字段的索引一个都没有,这就导致查询的压力很大,将请求全部阻塞住了,应用假死。
事后复盘:
1.Mongo不像MySQL是关系型的,迁移数据之前需要先建结构,责任人在迁移数据时执行脚本,文档接口直接生成,没有问题,就没有考虑索引的这方面。
2.Mongo链接没有设置超时时间。请求全部阻塞在等待Mongo数据返回,请求一直在到达服务器,然后堆积,拖垮了服务器,这个是应该设置超时时间的。
3.APP端的影响。APP对后端接口的调用,超时时间都是设置15分钟,APP的后台也被拖垮,这个超时时间设置太久了,不清楚他们是出于什么考虑。并且责任人给APP提供的接口是内网ip+端口的形式,没有通过域名走nginx,再加上APP端没有服务降级的措施,就会一直被C端用户访问,导致两方服务都挂掉,事态严重性升级。
问题二:OOM的发生
问题发生在第三天的上午,发现突然又有一台服务下线。查看服务日志,看不出什么有效信息:只是发现在OOM之前,有一些响应很快的接口,1ms、2ms的,会慢慢增加到几百、几千毫秒,再后来就OOM,CPU并没有异常,除了分析.hprof没有任何思路。
我使用的工具是JProfiler 10.1.3版本
dump文件导入后,内存溢出的大对象还是显而易见的,很标准的大对象
在这里插入图片描述
明显这两个ResultSet(项目使用的是MyBatisPlus)有问题,真的是太大了,选中其中一个对象,右键,查看具体的信息
在这里插入图片描述
在这里插入图片描述
我们先选择Outgoing references看这个对象都包含了哪些东西,其中一个rowData属性引起了我的注意,因为毕竟这是一个数据库返回结果集,理论上考虑也就是数据库返回的数据太多了,通过这一步真的看到查了二百多万条数据放入内存中。查了一下数据库表,基本上是全表查询了。接下来就是查这个对象是在哪产生的。
在这里插入图片描述
选择Incoming references,直接找一条数据点show more,就直接弹出了异常堆栈,看到这个我是真的高兴,有堆栈就有可能定位到问题,仔细看了堆栈,有我们项目中的代码。有了OOM这个现象,知道了这个对象为什么那么大(全表扫描了数据),再加上堆栈中指明的代码行数,就不能排查出问题,原因就不细说了。
在这里插入图片描述
事后复盘:
1.OOM的原因就是全表扫描将数据拿到内存中,最开始分析CPU、内存等数据的时候,也去RDS查了慢SQL,怀疑是不是有慢SQL导致接口响应变慢,高并发下拖垮了服务。其实当时是有留意到几条select * from table并且没有where 条件的语句。当时还以为是有人在Navicat端操作,因为测试和产品都有线上库的只读账号,怀疑是他们直接点开表,触发的这次查询,就没当回事儿。
2.这个接口是被外部系统调用的,两方责任人都有问题,他方的责任约定传数据(这个责任忽略不计),我方程序确实不严谨。跨团队的沟通应充分,对自己负责的模块应负责,对对接人不要盲目的相信,严谨自己模块的逻辑。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值