實操筆記:為 NSQ 配置監控服務的心路歷程

在 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 的官方文檔[//prometheus.io/docs/instrumenting/exporters/]上對 exporter 有推薦,我順着鏈接找到了官方推薦的 NSQ exporter[//github.com/lovoo/nsq_exporter]。NSQ exporter 這個項目年久失修,最近的一次提交已經在 4 年前。

於是,我把這個項目拿到了本地,做了一些簡單的改造, 使它支持 go mod。(PR 在這裡[//github.com/lovoo/nsq_exporter/pull/29])

NSQ exporter 部署完成後,接下來的問題是哪些指標需要監控?

參考官網[//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 當前狀況,在報警發出後及時人工處理跟進。相關業務的穩定性有明顯提升,此類問題引起的工單變少了;此外監控收集到的相關數據,讓我們在接下來的性能優化工作中的思路更加清晰,方向更加明顯。

Tags: