慢查询导致API服务雪崩案例分析

时间:2024-04-09 15:29:59

为什么要做这个案例分析?

因为在其他同学已经找到问题代码并修复后,我还没有彻底弄明白下面这2个问题:
  1.为什么是这段代码导致的?
  2.为什么看起来跟问题代码无关的接口也受影响变得恶化,这段代码到底是如何造成整个服务雪崩的?

在搞懂上面的一系列问题后,我认为这是一次典型的慢查询导致服务雪崩案例(因为没有其他次要因素),沉淀总结下来,或许可以帮助我下次更快更准的找到排查思路,而不至于没有方向浪费宝贵的排查时间,对于服务器问题线索的收集是有益的。

最容易获得的问题信息

服务质量下降后,一般最快能够获取到的信息,就是服务接口响应监控信息,例如这一次:访客服务API平均响应时长变慢,持续恶化,导致其他上游服务接口受影响

只要时间段选择长一点,就会发现接口响应时间从平均200+ms逐渐恶化到1min+
慢查询导致API服务雪崩案例分析

如何找到出问题的接口

影响平均响应时长的,应该是一些耗时比较长的接口拉高的,但怎么确认哪些接口是“罪魁祸首”,哪些接口是“受牵连”才恶化的?

在这个典型案例中,下面这两个步骤可以确定目标:

1)拉长监控时间范围,观察服务有恶化端倪的时间点

例如这个案例中,我们发现问题的时间点约11:30,把监控时间段调为11:00~12:00,不难观察服务有恶化端倪的是11:10开始逐渐恶化
慢查询导致API服务雪崩案例分析
2)监控开始时间调整到开始恶化的时间(11:10),结束时间不变,查看接口列表,按时间正序排序
慢查询导致API服务雪崩案例分析
这样做,主要是分析在服务开始恶化时,哪些接口已经出现问题了,而这部分接口往往就是主要问题甚至根本问题所在;顺便可以看到,一些接口在服务开始恶化时本来响应良好,随着时间增长不断才开始恶化的,这些往往都是“受牵连”的接口。

分析接口
本例中,接口线程分析显示耗时发生在mongo查询处。
解决的方式比较简单,也不是讨论的重点,一方面可以直接看看这段sql的语句是否有问题,另一方面可以通过数据库慢查询记录看看具体慢的原因。
慢查询导致API服务雪崩案例分析

为什么其他接口会受牵连恶化

服务从11:10开始恶化,从mongo监控看主库的CPU利用率有抖动
慢查询导致API服务雪崩案例分析
而从库则问题比较明显,CPU从11:10开始几乎持续跑满

慢查询导致API服务雪崩案例分析

再看看一个关键监控值:gl_cq_readers,其对应的应该是mongo命令db.serverStatus()的"globalLock.currentQueue.readers"字段值,阿里云对这个监控指标的解释如下:
慢查询导致API服务雪崩案例分析

简单来说,MongoDB中使用的是多粒度锁,在加锁时是一个层次性管理方式,从globalLock ===> DBLock ===> CollectionLock …,对于我们使用的WiredTiger引擎,读写并发时,使用的是文档级别锁。

慢查询导致API服务雪崩案例分析
这里套用下阿里云张友东的博客内容,

上述代码⾥,如果holder不为空,Client会先进去kQueuedReader或kQueuedWriter状态,然后获取⼀个ticket,获取到
后转换为kActiveReader或kActiveWriter状态。这⾥的ticket是什么东⻄?

这⾥的ticket是引擎可以设置的⼀个限制。正常情况下,如果没有锁竞争,所有的读写请求都会被pass到引擎层,这样
就有个问题,你请求到了引擎层⾯,还是得排队执⾏,⽽且不同引擎处理能⼒肯定也不同,于是引擎层就可以通过设置
这个ticket,来限制⼀下传到引擎层⾯的最⼤并发数。

wiredtiger设置了读写ticket均为128,也就是说wiredtiger引擎层最多⽀持128的读写并发(这个值经过测试是⾮常
合理的经验值,⽆需修改)。

而前面提到的“globalLock.currentQueue.readers”字段值,我的理解,就是目前等待提交到引擎层的请求排队数量,而当这个数量持续不为0时,说明系统的并发太⾼了,一般可以用下面两种方式解决:
1)通过优化单个请求的处理时间(⽐如建索引来减少COLLSCAN或SORT)
2)升级后端资源(内存、磁盘IO能⼒、CPU)

gl_cq_readers/writers带来的影响
案例中,主库在11:32:42监控到gl_cq_writers为18
慢查询导致API服务雪崩案例分析
从库从11:43开始,gl_cq_readers持续在25~37
慢查询导致API服务雪崩案例分析

而具体是writers或redaers无关紧要,主要是出现了currentQueue的堆积,那么这些处于等待队列的数据库请求耗时一定是比较长的,而这也是大部分“受牵连”的业务接口持续恶化的原因之一,反应出来的问题是并发太高,MongoDB服务质量下降。

遗留问题

本例中,在出现问题的一段时间内,从库的CPU利用率持续在99%(不少接口在这个时间点出现超时),是否考虑下提升该数据库的硬件配置,以提升服务处理能力?
慢查询导致API服务雪崩案例分析

总结

通过这次问题的分析,反推一下这次的关键线索:
1)服务接口整体变慢,包括那些平时良好的接口
2)gl_cq_readers/writers指标变化,持续不为0
3)MongoDB CPU持续飙高

而后续接收到服务响应变慢的告警时,基本可以先用下面几个步骤找到/排除典型慢查询的问题:
1)找到服务出现问题的时间点
2)找到该时间点的主要问题接口,分析接口超时原因
3)如果因为数据库查询耗时严重,到mongo监控中看下CPU利用率
4)观察gl_cq_readers/writers指标
5)修复慢查询,发布验证