網易音樂訊息佇列實踐調研
業務背景
網易雲音樂從13年4月上線以來,業務和使用者突飛猛進。後臺技術也從傳統的 Tomcat 叢集到分散式微服務快速演進和迭代,在業務的不斷催生下,誕生了雲音樂的 RPC,API 閘道器和鏈路跟蹤等多種服務,訊息佇列也從 RabbitMQ 叢集遷移到 Kafka叢集。對於訊息佇列,更多處於使用階段,也在使用中出現很多問題。因此我們期望提供一種完全可控,出現問題我們自己能排查,能跟蹤,可以根據業務需求做定製改造的訊息佇列。
生產環境
截止到2019年Q1,基於 RocketMQ 改造實現的訊息佇列在網易雲音樂生產環境已經有6個叢集。涉及順序訊息,普通訊息,多種高可用高可靠要求。
接入應用 數量 200+,每條業務線核心業務都有涉及。峰值 QPS 已達 30w+,topic 800+。在測試環境單個叢集,由於環境很多,Topic 數量也瘋長,單個達到 4000+,未來隨著 kafka 遷移的更多,Topic 數量還會不斷上漲。
從 2018 年 11 月開始,禁止新業務接入kafka,新接入全部使用 RocketMQ,自2019 Q1推動Kafka業務遷移到RocketMQ,目前已經遷移70%+,業務整體穩定性得到極大提升。
隨著業務接入 RocketMQ 的增多,也不斷催生下游大資料生態的接入和使用。雲音樂大資料主要使用 flink,目前 flink 在執行 job 60+,其中 RocketMQ 訊息量 每天達 8 億 +,這一塊未來還有不少增長空間。
技術選型
RocketMQ vs RabbitMQ vs Kafka效能對比
由於RabbitMQ持久化效能只有2.6萬/秒,不能滿足業務對高效能、高吞吐的要求。所以2017年從RabbitMQ遷移到Kafka
功能特性完備性對比
RocketMQ系統架構
開源RocketMQ主要問題如下:
- Broker僅提供了Master到Slave的複製功能,沒有Failover切換的能力
- 事物訊息不開源(我們開始研發時不開源)
- 訊息傳送消費無追蹤(我們開始研發時不開源)
- 告警與監控體系沒有
- 開源控制檯不完善
業務要求
- 具備自主failover切換能力
- 監控dashboard大盤
- 根據不同業務場景提供靈活適配的QOS能力。如商城訊息不能丟失,交易事物訊息支援,訊息傳送消費追蹤,失敗排查等能力
- 提供傳送耗時,消費耗時,消費延遲,消費失敗異常等提供監控和告警能力
- 功能強大和較完善的管理控制檯
- 對Nodejs和Python支援,另外要提供http接入能力
優化架構設計
以開源RocketMQ為核心,完全繼承開源 RocketMQ 具備的特性,然後以此為基礎進行擴充套件
改進措施:
- 通過新增對broker健康檢查,提供主從broker自主failover能力
- 傳送耗時,消費耗時,消費失敗異常採集上報,寫入ES,根據閥值配置監控項
- 有broker宕機,提供服務降級元件
- 系統異常時,客戶端會將訊息傳送本地或者傳送到容災叢集,降低系統宕機時對業務的影響。
- 提供系統巡檢能力,關鍵關鍵狀態異常快速傳送報警
各元件互動流程如下:
- NameServer提供topic路由資訊發現,配置中心能力。
- Broker 提供 topic 訊息儲存,索引,查詢。同時 Broker 自身提供 HA 需要的複製,角色修改,探活,狀態獲取等 API。同時 Broker 定時向所有 Nameserver 註冊。
- Nginx 提供發現 NameServer 能力,由運維將 nameserver 列表填寫到 hotdoc 中。避免 NameServer 變更業務重新配置上線。
- 降級元件提供訊息傳送失敗的處理,在訊息傳送失敗的情況下 client 會將訊息傳送到容災叢集,由降級元件統一處理保證傳送方業務的穩定性。
- Failover 元件檢查 Broker 狀態,Broker 宕機根據 QOS 要求切主。
- Console 提供資源管控,訊息查詢,軌跡跟蹤,監控報表,監控告警配置,死信重投等能力。
- 巡檢元件巡檢訊息佇列自身叢集所有元件健康與服務狀態,有異常提前通知運維和訊息佇列相關人員。
- 監控元件提供監控報表資料採集處理,訊息佇列大盤資料採集處理。
- 告警元件主要採集告警資訊,根據控制檯配置的告警閥值和人員資訊通知相應業務方。
- 訊息佇列大盤提供訊息佇列叢集自身的監控狀態,主備複製狀態,QPS 等叢集大盤報表展示。
新增高階特性
RocketMQ為成為Apache頂級專案前,github開源版本是沒有訊息軌跡跟蹤和事務特性的。網易雲音樂對程式碼進行了修改和擴充套件,用於支援一下一些特性:
- 訊息軌跡跟蹤
- 事務訊息
- 多環境隔離
- 消費執行緒池自定義
- 消費限流與降級
訊息軌跡
以上實現和開源RocketMQ-v4.4中提供的訊息軌跡實現機制一樣。和開源不同的是,雲音樂訊息佇列提供傳送消費、事物訊息回查軌跡,同時消費失敗時,也在軌跡中提供失敗異常資訊,這樣就能夠追蹤失敗原因。
事務訊息
雲音樂通過修改儲存引擎實現自己的事物訊息。提供事務訊息回查按時間收斂能力,回查不到狀態超過次數進入死信,同時提供死信告警,事務訊息回查死信處理能力。
多環境隔離
雲音樂有很多條業務線,每條業務線都有很多個需求在做,同時各個業務線之間的訪問都是通過服務化的方式進行。為提升開發和測試效率,通過對 RPC 流量打標,的方式將流量隔離到相應環境,並一路透傳下去。訊息也一樣,同一個需求傳送的訊息需要相應的環境開發,測試,和其他互不影響。因此雲音樂設計實現了訊息佇列的隔離,加快業務開發測試,預發快速驗證能力。
消費執行緒池自定義支援
開源 RocketMQ 消費端僅有一個消費執行緒池,多個topic的消費會互相影響。另外同一個消費端僅有一個 listener,如果是多個 topic,需要上層業務分發。雲音樂同一個應用都會有多個topic消費,有的多達 30+ 個。因此優先順序高的 topic 需要自定義自己的消費執行緒池,優先順序低的使用公共的。另外 每個topic也要有自己的listener,這樣就不用上層分發。基於上述要求,我們增加訂閱可以同時指定listener和consumeThreadExecutor 的方式。
消費限流與降級
開源RocketMQ並沒有提供消費限流能力,基於Sentinel的是pull模式,而不是 push 模式,不能很好滿足雲音樂的業務需求。雲音樂的訊息消費不少都要寫資料庫或者訪問第三方,這些消費和線上業務都是同一個應用,訊息佇列自身雖然具備削峰填谷的能力,但是消費端會最大化使用消費執行緒池,這會對線上業務也產生影響。為保證線上業務優先,需要限制消費的速度,減少瞬時高峰訊息消費對線上業務的影響。這部分可以通過調整消費執行緒池和消費qps來調整。我們選擇了調整消費 qps 消費限流的方式,這樣能和監控資料對起來並提供控制檯動態調整能力,消費執行緒池調整雖然我們也提供動態調整執行緒池能力但是並不是線性的,調整起來沒有參考,比較困難。消費限流做在了底層而不是讓應用層自己做,和上層的區別時,上層限流了會觸發訊息消費一次並且失敗,底層不會失敗也不算消費一次,因為還沒投遞上層業務。
多機房網路bug修復
雲音樂有部分業務部署在建德,需要消費杭州的資料。這部分消費的機器總是隔三差五報 timeout。經過排查,發現 client 新建的連線總是在關閉建立迴圈,非常不穩定,這部分排查 remoting 層的程式碼發現 client 建立連線存在併發問題,會將建立好的連結關閉。定位待開源 client 的 remoting bug 後,我們進行了修復。另外後來幾天,曲庫的業務同學也報傳送3s超時,經過仔細排查,發現異常日誌和連線建立日誌和網路建立併發問題的日誌一致,協同業務升級到最新修復的客戶端解決。業務升級上線後如上所示,傳送非常平穩,不再超時。
回饋開源社群
作為開源的受益者,部分改動已經提交到Apache RocketMQ官方且被採納,如消費限流,消費執行緒池,網路 bug 修復等。
未來規劃與展望
- 從核心歌單和曲庫業務都有QPS高吞吐的push業務在執行,後續推廣到日誌領域。
- 涉及到日誌傳輸開源 RocketMQ 有部分效能問題,需要做優化,目前我們已經完成這部分優化,由於優先順序的關係,還沒推廣到日誌傳輸相關應用。我們期望雲音樂的訊息佇列能夠拓展到日誌方面,將訊息佇列具備的完善監控告警等能力賦能到大資料,NDC 訂閱(資料庫更新訂閱服務)。同時增加路由能力減少多機房間跨機房訪問。
- RocketMQ只有網易音樂使用,未來聯合杭研,將網易音樂RocketMQ貢獻的擴充套件版推廣到其他大產品線。
參考資料
網易雲音樂的訊息佇列改造之路:https://www.infoq.cn/article/2_D683SzYss0PjMdKXg2
部落格引用地址:https://www.cnblogs.com/lizherui/p/12659030.html