在 Go 語言實現的實時訊息佇列中, NSQ 的熱度可以排第一。
NSQ 這款訊息中介軟體簡單易用,其設計目標是為在分散式環境下執行,為去中心化服務提供一個強大的基礎架構。它具有分散式、去中心化的拓撲結構,該結構具有無單點故障、故障容錯、高可用性以及能夠保證訊息的可靠傳遞的特徵。
NSQ 以分散式架構, 能夠處理數億級別的訊息能力俘獲了眾多 gopher 的心。 我司也不例外,較多的業務都依賴 NSQ 做訊息推送。今天我想和大家嘮一嘮關於 NSQ 監控的問題。
為什麼要部署監控?
監控的重要性大家應該都清楚。沒有監控的服務就是 “盲人騎瞎馬,夜半臨深池”。 這樣講可能有些抽象,我來給大家分享一個親歷的真實案例吧。
還記得那天,我正吃著火鍋唱著歌,心裡甭提有多美了,突然手機響了,開啟一看,發現有客戶反饋 CDN 重新整理成功後未生效的問題。
火鍋是不可能繼續愉快地吃了,我抱起電腦一頓操作猛如虎,可惜結果不靠譜: 我查了系統呼叫鏈路上相關服務的日誌,但是客戶需要重新整理的 URL 卻沒在日誌中查到任務蛛絲馬跡。那問題出在哪呢?
這塊業務涉及到的服務呼叫示意圖如上圖所示。因為客戶需求的緊急,我也把視線從沸騰的火鍋收了回來,對著服務鏈路圖沉思起來:
-
如圖所示,使用者成功提交了重新整理請求說明請求流轉到了 ohm 服務層,並且 ohm 成功處理了這個請求。
-
ohm 服務是重新整理預熱相關業務的 gateway,記錄的是 ERROR 級的 log。沒有在 ohm 的日誌中查到 該請求的相關的記錄,表明 ohm 向下遊的 NSQ 推送訊息的動作是成功的。
-
NSQ 對應的消費者是 purge 和 preheat 元件。purge 負責執行重新整理動作,它記錄的日誌是 INFO 級,每一條重新整理的 URL 它都會記錄到日誌中。 但是為什麼在 purge 中卻查不到相關日誌?
剛才我就卡在了這裡。問題的癥結在於哪些情況下會在 purge 服務中查不到對應的日誌。我大致列舉了如下幾種情況:
-
服務變更。purge 服務如果最近更新的程式碼如果有 Bug 可能導致了異常。但是我很快排除了這點,因為釋出記錄中,這個服務最近幾個月都沒人動過。
-
NSQ 壞了。這個更不靠譜,NSQ 是叢集部署的,單點故障可以避免,全域性故障的話恐怕公司群現在已經炸翻了天。
-
NSQ 沒把訊息發過來。但是 NSQ 是實時訊息佇列,訊息投遞應該很快,而且客戶的重新整理操作是在幾個小時前了。
會不會因為 NSQ 訊息堆積了,才沒及時把訊息投遞過來呢?之前在測試環境沒有發現此類問題,因為測試的量級與線上環境相比遠遠不夠 ... 想到這,有點茅塞頓開的感覺。登入 NSQ 的控制檯看對應的 Topic,果然問題出現在這,NSQ 上未投遞的訊息已經堆積了幾億條!
問題定位了,後續先通過內部工具先替客戶解決問題就屬於常規操作了,這裡就不展開了。
監控部署落地
工單處理完了,我鬆了一口氣,但是事情並沒有告一段落。這個故障算是敲響了警鐘:不能覺得 NSQ 效能不錯就認為訊息不會堆積了,必要的監控報警還是得安排上。
因為我司已經存在的基礎設施,所以我決定使用 Prometheus 來監控 NSQ 服務。(Prometheus 的相關背景知識就不在這裡科普了, 想看的請留言。)
Prometheus 通過 exporter 去採集第三方服務的資料,也就是說 NSQ 必須配置一個 exporter 才能接入 Prometheus。
Prometheus 的官方文件[https://prometheus.io/docs/instrumenting/exporters/]上對 exporter 有推薦,我順著連結找到了官方推薦的 NSQ exporter[https://github.com/lovoo/nsq_exporter]。NSQ exporter 這個專案年久失修,最近的一次提交已經在 4 年前。
於是,我把這個專案拿到了本地,做了一些簡單的改造, 使它支援 go mod。(PR 在這裡[https://github.com/lovoo/nsq_exporter/pull/29])
NSQ exporter 部署完成後,接下來的問題是哪些指標需要監控?
參考官網[https://nsq.io/components/nsqadmin.html]我認為這些指標需要重點關注:
-
Depth:當前 NSQ 堆積的訊息。NSQ 在記憶體中預設只儲存 8000 訊息,超過的訊息會持久化到磁碟中。
-
Requeued:訊息 requeue 的次數。
-
Timed Out:處理超時的訊息。
Prometheus 建議配置 Grafana 更加直觀地檢視指標的變動情況,我配置大體的效果如下:
超時訊息對應著 Timed Out 指標
-
堆積訊息對應著 Depth 指標
-
負載是根據公式 sum(irate(NSQ_topic_message_count{}[5m])) 生成的。
-
探測服務是探測 NSQ exporter 服務是否正常。 因為該服務經常會因為 NSQ 壓力過來導致 exporter 自身服務不可用。
自從 NSQ 配置監控服務後,我們能迅速感知 NSQ 當前狀況,在報警發出後及時人工處理跟進。相關業務的穩定性有明顯提升,此類問題引起的工單變少了;此外監控收集到的相關資料,讓我們在接下來的效能優化工作中的思路更加清晰,方向更加明顯。