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動態配置能力支持,支持灰度配置變更