Pulsar 在騰訊雲的穩定性實踐

語言: CN / TW / HK

導語

2022騰訊全球數字生態大會已圓滿落幕,大會以“數實創新、產業共進”為主題,聚焦數實融合,探索以全真互聯的數字技術助力實體經濟高質量發展。大會設有29個產品技術主題專場、18個行業主題專場和6個生態主題專場,各業務負責人與客戶、合作伙伴共同總結經驗、凝結共識,推動數實融合新發展。

本次大會設立了微服務與中介軟體專場,本專場從產品研發、運維等最佳落地實踐出發,詳細闡述雲原生時代,企業在開發微服務和構建雲原生中介軟體過程中應該怎樣少走彎路,聚焦業務需求,助力企業發展創新。

隨著大資料時代的到來,企業在生產和經營活動中產生的各類資料正以前所未有的速度增長,通過對實時及歷史資料的融合分析,及時挖掘業務洞察和輔助決策,已成為企業的普遍行動。在雲原生的浪潮下,企業需要聚焦業務,迫切需要簡單易行,零程式碼地配置搭建起自己的可以達到將本增效效果的資料鏈路系統。

本篇文章將從以下幾個方面來跟大家一起分享 Pulsar 在騰訊的實踐中遇到的問題和挑戰以及對應的解決方案。

● 訊息佇列發展歷史

● 開源方案可能面臨的問題和挑戰

● 我們的探索與解決方案

● Pulsar 在騰訊內部的案例實踐

● TDMQ 未來規劃

訊息佇列發展歷史

下圖是開源社群整個訊息中介軟體產品,從2003年誕生的 ActiveMQ 到2012年 誕生的 Pulsar 的整個發展過程。

在這個發展過程中,不同的產品解決了各種各樣不同的問題。下圖是各產品之間的對比,大家最關注的是線上訊息和離線訊息,現在業界比較通用的會把 Kafka 用在離線訊息上,線上訊息更多采用的是 RocketMQ。RabbitMQ可能在擴充套件性上存在一些差異,但是它簡單易用,歷史也更悠久。規模決定了這些訊息產品的擴充套件性如何,能否支援十萬或者百萬的訊息 Topic 的量級,下表中對最小規模也做了詳細對比。

Pulsar 誕生的背景和原因

看了以上那麼多訊息產品的對比,大家肯定會有一個疑問,既然已經有這麼多的訊息產品了,為什麼還要用 Pulsar?Pulsar 它存在的意義是什麼呢?基於 Pulsar 研發人員自己的經驗以及社群的背景,Pulsar 有三個值得關注的發展方向:雲原生環境適配、多租戶和海量 Topic、離線上流批一體。

雲原生環境適配

● 計算與儲存分離的架構,對於原生的 K8s 或者容器化的環境是更加友好的,天然適配雲原生環境,不同的元件可以分開擴充套件。

● 基於對機器容災的考慮,支援跨 Region/ 機架資料寫入。

● 對於普通使用者,可以方便的使用開源的 Operator 在雲環境直接部署,真正的服務於業務。

多租戶和海量 Topic

● 天然支援多租戶, Namespace 和 Topic 級別的許可權管理,可以做共享大叢集。

● 設計層面支援海量 Topic,對於有這類需求的使用者有比較強的吸引力。

離線上流批一體

● 在系統維護層面,All in one 的吸引力。

● 對業務只需要維護一套中介軟體即可實現流批一體。

● Kafka 等 Connector 的存在,遷移方便。

普遍情況下離線會採用 Kafka,線上會採用 RocketMQ,但實際上,很多使用者或者很多基礎設施的同學團隊,更希望有一款產品能夠把離線和線上結合起來,具有 All in one 的能力。Pulsar 在設計之初就是有這樣的考量,也參考了前者的一些優勢。

Pulsar 的整體架構

上圖左下角的部分可以看成一個整體,是 Pulsar 的一個 Broker 叢集,也就是前面介紹到的計算節點,右側 Bookeeper 是 Pulsar 的儲存節點,也就是存算分離中的存,Zookeeper 是 Pulsar 元資料管理中心,這是整個分散式的部署環境。大家可以看到整體的架構包括三個部分:

● 2Broker+3Zookeeper+3Bookeeper,這是一個最小叢集結構。

● 多語言 SDK,Java/Go/C++/Node,對應的是上圖的上半部分,Pulsar 現在多語言 SDK 也是比較豐富的,用的最多的就是 Java/Go/C++/Node 等。

● 一些 Manager 的管控 UI,這部分在社群相對不是特別完善。

開源方案面臨的問題和挑戰

開源方案面臨的問題

管控面

1、元資料資源的許可權管理,如何劃分不同的使用者和不同的許可權。

2、當一個叢集超過一定的規模,海量 Topic (3w 分割槽)的情況下,策略更新對管控穩定性產生影響。

3、使用者對元資料( Topic 等)進行管理出現問題,比較難以定位,沒有操作軌跡。

資料面

1、線上訊息生產限流之後,客戶端無法明確感知,對生產穩定性有影響。

2、不少配置項缺少動態能力,進行更新時需要重啟 Pulsar。

3、不同網路環境下面,ListenName 的網路方案擴容不友好。

4、出現訊息空洞時,無法自動恢復。

5、如果叢集容量不足,如何將使用者從一個叢集無縫遷移到另一個叢集減輕叢集壓力

可觀測性

1、海量 Topic 的資料指標上報, Promethus 一次性產生幾十MB資料,對 Broker 有較大效能影響。

2、服務端訊息軌跡,服務提供方和使用者側無法對一條訊息的軌跡進行追溯。

3、 針對複雜的生產問題,無法提前發現,如 Unack 導致 Backlog 堆積。

基於以上三個方面的問題,開源方案遇到的挑戰也有三個方面:

● 百萬級 Topic 支撐,如何保障效能和穩定性?

● 生產級運維要求,如何快速預警排查定位問題?

● 多業務場景共享,如何精細化安全管控和治理?

我們的探索與解決方案-管控面

存在問題:

1、效能:對 Broker 能承受什麼樣的量級要有感知,感知來源不能是普通的壓縮資料,比如說大家從開源社群裡看到的一些指標在當前的場景下適不適用要存疑,頻繁操作資源會導致Broker 不穩定。

2、穩定性:在部分場景下,當 Topic 資料很多,或者執行時間足夠長,會存在一定的 Zookeeper 元資料洩漏,元資料會越積越多,因為目前 Pulsar 版本對 Zookeeper 有強依賴,所以如果 Znote 無限增長,那麼最終對穩定性有極高的影響。

3、可運維性:當資源出現不符合預期的場景時,無法追蹤每次請求的資訊。

解決方案:

● 效能優化:Broker 操作資源效能優化+專享壓測保障 + 生產大規模叢集驗證,保證可以支援操作元資料1000TPS長時間執行沒有問題;

● 針對穩定性影響的問題,做了運維管理系統,可以觀測 Znote 的增量,知道哪些增量是不符合預期的,能通過和 Broker 元資料做比對,校驗元資料是否有邏輯問題,不該增長,便於自助訂正與運維;

● 元資料儲存標籤,對事後資料分析提供支援;

● 資源管理軌跡,保證每筆資源操作資訊可查。

我們的探索與解決方案-資料面

當把管控面的問題解決之後,生產更多要關注資料面的穩定性問題,資料面的穩定性其實就包括兩部分生產和消費。

存在問題:

1、生產消費問題:限流場景使用者無法感知,空洞訊息的問題,可能需要重啟或者服務端去幫使用者做 Unload 的操作。

2、網路方案:使用者通過 ListenerName 的方式接入存在一定的感知,但需要擴容的時候運維不夠靈活。

3、效能穩定性:Pulsar 裡有快取的概念,那麼快取的有效性命中率有多高,在共享的場景下

需要做判斷或者壓測,需要做快取的集中式的管理,包括對整個 Pulsar 儲存場面 BK 的一些穩定性的優化。

4、可運維性:不少配置項需要重啟 Broker 機器生效,在運維場景下不夠友好,對線上訊息的場景影響較大,使用者訊息的軌跡無法確認,但對離線場景感知不明顯。

解決方案:

● 支援空洞訊息的主動推送,Pulsar 在服務端能感知到空洞訊息,因為 Pulsar 有一個記錄,是已經被確認的訊息的集合,這樣在服務端去判斷空洞訊息的時候就是看它在服務端是否超過了使用者配置的時間,比如,使用者認為拿到一條訊息到消費完最多需要10秒,那麼就可以10秒檢測一次,如果發現這個訊息在空洞訊息列表裡存在了10秒,Pulsar 就會主動推給使用者,解決使用者單機常見的問題。

● 生產限流的場景下,Pulsar 也支援 Failfast 的邏輯,如果你被限流了,可以把限流的異常直接返回給使用者,這樣的話使用者也就可以很快的知道這個場景,他能去做對應的邏輯處理。

● 通過泛域名的分配與解析,解決使用者需要指定 listenerName 的問題,提升後期的運維靈活性;

● 支援 OHC+LRU 的全域性快取策略,修復 BK 穩定性 Bug Fix,效能和穩定性會有較大提升。

● 對於可運維性上的配置項問題,其實社群目前的動態配置主要是基於 ZK 的,當你的程式碼層面上支援了動態配置,你可以通過去操作 Pulsar 的動態配置的命令將這個資料寫入 ZK,然後 Broker 會監聽到 ZK 的變化,然後去更新記憶體的這種配置,這樣的話,首先需要去做一些程式碼層面的改動,動態運維的東西都要動態調整,這裡麵包括負載均衡的比例、策略等,社群後面也會對 ZK 做一些相應的替換,我們更希望與運維相關的動態配置有一個通用的地方去儲存,程式碼級別支援Apollo動態配置,包括騰訊雲內部的動態配置。這樣對於運維管控就不依賴於 ZK 的穩定性。

● 在訊息軌跡層面,在 Broker 的程式碼層面,做了一些 Feature。就是當用戶傳送訊息的時候,我們會把使用者傳送訊息的客戶端的來源 IP、訊息 ID 以及傳送訊息的耗時等這些資訊,記錄下來組成一筆軌跡;當這條訊息被消費的時候,也會記錄一條軌跡,包括哪一臺客戶端,哪一個 Consumer 去消費;當用戶把這條訊息真正去 Ack 的時候,也會做相應的軌跡,最終會呈現給使用者一個產品化的東西,當用戶發現某一筆訊息沒有被正常消費的時候,他可以拿訊息ID來運維管控端查詢,我們會告訴他這個訊息有沒有被推過,推了幾次,目前這個訊息在哪裡。

我們的探索與解決方案-可觀測性

存在問題:

1、海量topic:exporter 造成頻繁的gc;

2、broker軌跡:生產消費,資源管理服務端無軌跡;

3、監控報警:需要使用者配置一套報警系統和規則;

4、指標複雜:如何有效監控預警

解決方案:

● 資訊主動上報:當 Topic 很多的時候,當 Brocker 上有3萬分區的時候,每次 Promethus 去拉取使用者的指標時,需要產生一個 String 的資料,這個資料需要一次性報給 Promethus,通過我們的判斷,可能會出現幾十兆,上百兆的資料,這樣一分鐘拉取一次,對服務端的GC壓力非常大,服務端的效能就會下降的比較明顯。如果把拉的方式改成推的方式,在程式碼層面,週期性的把記憶體中的這種資料做拆分,比如每5個 Topic 上報一次,我們在服務端做這樣的聚合,好處在於,把一次性的這種資料變成了類似於流的處理,這樣的話,效能和穩定性也會有較大的提升。

● 全鏈路跟蹤,支援訊息軌跡和資源管理軌跡。

● 精細化監控,對接雲監控與報警系統,支援精細的監控與報警。

● 自動化巡檢:社群的版本,指標是比較完善的,我們可以通過各種各樣的指標來判斷服務端目前的健康狀態,包括使用者的消費情況,真正使用者使用的情況下會發現一些問題,主要原因是指標確實很多也很複雜,對使用者來說,他要理解這個指標,並且通過這個指標來判斷自己的問題,是比較困難的,騰訊雲 TDMQ 做了自動化巡檢,針對複雜的指標有效性問題,通過自動化巡檢系統,主動觸達使用者。

Pulsar在騰訊內部的案例實踐-王者營地

王者營地App 對使用者的登入登出狀態,組隊狀態,房間狀態,局內高光資料,擊殺資料等使用者的消費狀態,生產到 Pulsar 叢集,這些行為的消費方會在 Pulsar裡面去消費,通過 TDMQ Pulsar 削峰填谷,以及 Shared 的訂閱模式,進行訊息的分發。如果不用訊息的話,下圖左側的生產方,需要感知他所有的消費方,並且對所有的消費方做一次RPC的呼叫,成本較高。包括很多訊息不是需要實時性的,通過削峰填谷可以減少業務的壓力。下面是一些實踐情況。

● 通過不同的 Topic 字尾來區分不同環境。

● 由於業務上過期資料可以不消費,因此設定了2小時的ttl過期時間。

● 客戶端使用 Golang pulsar sdk。

● 吞吐量級:十萬級生產,十萬級消費。

基於以上場景,騰訊雲在生產商推薦使用者使用最多的是 Java 和 Go 的 SDK,同時也更推薦使用者們使用 Shared 的訂閱模式,包括 Namespace 的策略上,也更建議使用者根據自己的場景來決定是不是需要消費過期,是不是需要設定一些訊息保留的機制,方便使用者後期的一些回溯。

TDMQ 未來規劃

前面介紹了很多,大家在自己的實際使用場景中,不管是自建還是做開源社群的開發,或者是自己公司內部使用 Pulsar,如果大家遇到以上類似的問題,都可以參考以上的優化方案或者去跟進社群的新版本,騰訊雲開發的 Pulsar 也會盡量跟社群保持一致,並貢獻給社群。後續也會在以下幾個方面做更多的努力。

● 支援根據業務 ID 的訊息軌跡查詢

● 增強運營管控端業務可理解的指標豐富度

● 運維測支援訊息生產消費問題診斷

● 優化大規模超長延遲訊息

● Broker動態配置能力支援,支援灰度配置變更