慢查詢導致API服務雪崩案例分析

爲什麼要做這個案例分析?

因爲在其他同學已經找到問題代碼並修復後,我還沒有徹底弄明白下面這2個問題:
  1.爲什麼是這段代碼導致的?
  2.爲什麼看起來跟問題代碼無關的接口也受影響變得惡化,這段代碼到底是如何造成整個服務雪崩的?

在搞懂上面的一系列問題後,我認爲這是一次典型的慢查詢導致服務雪崩案例(因爲沒有其他次要因素),沉澱總結下來,或許可以幫助我下次更快更準的找到排查思路,而不至於沒有方向浪費寶貴的排查時間,對於服務器問題線索的收集是有益的。

最容易獲得的問題信息

服務質量下降後,一般最快能夠獲取到的信息,就是服務接口響應監控信息,例如這一次:訪客服務API平均響應時長變慢,持續惡化,導致其他上游服務接口受影響

只要時間段選擇長一點,就會發現接口響應時間從平均200+ms逐漸惡化到1min+
在這裏插入圖片描述

如何找到出問題的接口

影響平均響應時長的,應該是一些耗時比較長的接口拉高的,但怎麼確認哪些接口是“罪魁禍首”,哪些接口是“受牽連”才惡化的?

在這個典型案例中,下面這兩個步驟可以確定目標:

1)拉長監控時間範圍,觀察服務有惡化端倪的時間點

例如這個案例中,我們發現問題的時間點約11:30,把監控時間段調爲11:00~12:00,不難觀察服務有惡化端倪的是11:10開始逐漸惡化
在這裏插入圖片描述
2)監控開始時間調整到開始惡化的時間(11:10),結束時間不變,查看接口列表,按時間正序排序
在這裏插入圖片描述
這樣做,主要是分析在服務開始惡化時,哪些接口已經出現問題了,而這部分接口往往就是主要問題甚至根本問題所在;順便可以看到,一些接口在服務開始惡化時本來響應良好,隨着時間增長不斷纔開始惡化的,這些往往都是“受牽連”的接口。

分析接口
本例中,接口線程分析顯示耗時發生在mongo查詢處。
解決的方式比較簡單,也不是討論的重點,一方面可以直接看看這段sql的語句是否有問題,另一方面可以通過數據庫慢查詢記錄看看具體慢的原因。
在這裏插入圖片描述

爲什麼其他接口會受牽連惡化

服務從11:10開始惡化,從mongo監控看主庫的CPU利用率有抖動
在這裏插入圖片描述
而從庫則問題比較明顯,CPU從11:10開始幾乎持續跑滿

在這裏插入圖片描述

再看看一個關鍵監控值:gl_cq_readers,其對應的應該是mongo命令db.serverStatus()的"globalLock.currentQueue.readers"字段值,阿里雲對這個監控指標的解釋如下:
在這裏插入圖片描述

簡單來說,MongoDB中使用的是多粒度鎖,在加鎖時是一個層次性管理方式,從globalLock ===> DBLock ===> CollectionLock …,對於我們使用的WiredTiger引擎,讀寫併發時,使用的是文檔級別鎖。

在這裏插入圖片描述
這裏套用下阿里雲張友東的博客內容,

上述代碼⾥,如果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
在這裏插入圖片描述
從庫從11:43開始,gl_cq_readers持續在25~37
在這裏插入圖片描述

而具體是writers或redaers無關緊要,主要是出現了currentQueue的堆積,那麼這些處於等待隊列的數據庫請求耗時一定是比較長的,而這也是大部分“受牽連”的業務接口持續惡化的原因之一,反應出來的問題是併發太高,MongoDB服務質量下降。

遺留問題

本例中,在出現問題的一段時間內,從庫的CPU利用率持續在99%(不少接口在這個時間點出現超時),是否考慮下提升該數據庫的硬件配置,以提升服務處理能力?
在這裏插入圖片描述

總結

通過這次問題的分析,反推一下這次的關鍵線索:
1)服務接口整體變慢,包括那些平時良好的接口
2)gl_cq_readers/writers指標變化,持續不爲0
3)MongoDB CPU持續飆高

而後續接收到服務響應變慢的告警時,基本可以先用下面幾個步驟找到/排除典型慢查詢的問題:
1)找到服務出現問題的時間點
2)找到該時間點的主要問題接口,分析接口超時原因
3)如果因爲數據庫查詢耗時嚴重,到mongo監控中看下CPU利用率
4)觀察gl_cq_readers/writers指標
5)修復慢查詢,發佈驗證

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章