Apache Pulsar在BIGO的性能調(diào)優(yōu)實戰(zhàn)是怎樣的,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
專注于為中小企業(yè)提供網(wǎng)站制作、成都做網(wǎng)站服務(wù),電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)燈塔免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了成百上千企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。
在人工智能技術(shù)的支持下,BIGO 基于視頻的產(chǎn)品和服務(wù)受到廣泛歡迎,在 150 多個國家/地區(qū)擁有用戶,其中包括 Bigo Live(直播)和 Likee(短視頻)。Bigo Live 在 150 多個國家/地區(qū)興起,Likee 有 1 億多用戶,并在 Z 世代中很受歡迎。
隨著業(yè)務(wù)的迅速增長,BIGO 消息隊列平臺承載的數(shù)據(jù)規(guī)模出現(xiàn)了成倍增長,下游的在線模型訓(xùn)練、在線推薦、實時數(shù)據(jù)分析、實時數(shù)倉等業(yè)務(wù)對消息的實時性和穩(wěn)定性提出了更高的要求。
BIGO 消息隊列平臺使用的是開源 Kafka,然而隨著業(yè)務(wù)數(shù)據(jù)量的成倍增長、消息實時性和系統(tǒng)穩(wěn)定性要求不斷提高,多個 Kafka 集群的維護成本越來越高,主要體現(xiàn)在:
數(shù)據(jù)存儲和消息隊列服務(wù)綁定,集群擴縮容/分區(qū)均衡需要大量拷貝數(shù)據(jù),造成集群性能下降
當分區(qū)副本不處于 ISR(同步)狀態(tài)時,一旦有 broker 發(fā)生故障,可能會造成丟數(shù)或該分區(qū)無法提供讀寫服務(wù)
當 Kafka broker 磁盤故障/使用率過高時,需要進行人工干預(yù)
集群跨區(qū)域同步使用 KMM(Kafka Mirror Maker),性能和穩(wěn)定性難以達到預(yù)期
在 catch-up 讀場景下,容易出現(xiàn) PageCache 污染,造成讀寫性能下降
雖然 Kafka 的 topic partition 是順序?qū)懭?,但是?broker上有成百上千個topic partition 時,從磁盤角度看就變成了隨機寫入,此時磁盤讀寫性能會隨著 topic partition 數(shù)量的增加而降低,因此 Kafka broker 上存儲的 topic partition 數(shù)量是有限制的
隨著 Kafka 集群規(guī)模的增長,Kakfa 集群的運維成本急劇增長,需要投入大量的人力進行日常運維。在 BIGO,擴容一臺機器到 Kafka 集群并進行分區(qū)均衡,需要 0.5人/天;縮容一臺機器需要 1 人/天
為了提高消息隊列實時性、穩(wěn)定性和可靠性,降低運維成本,我們重新考慮了 Kafka 架構(gòu)設(shè)計上的不足,調(diào)研能否從架構(gòu)設(shè)計上解決這些問題,滿足當前的業(yè)務(wù)要求。
Apache Pulsar 是 Apache 軟件基金會頂級項目,是下一代云原生分布式消息流平臺,集消息、存儲、輕量化函數(shù)式計算為一體。Pulsar 于 2016 年由 Yahoo 開源并捐贈給 Apache 軟件基金會進行孵化,2018 年成為Apache 軟件基金會頂級項目。
Pulsar 采用計算與存儲分離的分層架構(gòu)設(shè)計,支持多租戶、持久化存儲、多機房跨區(qū)域數(shù)據(jù)復(fù)制,具有強一致性、高吞吐以及低延時的高可擴展流數(shù)據(jù)存儲特性。
Pulsar 吸引我們的主要特性如下:
線性擴展:能夠無縫擴容到成百上千個節(jié)點
高吞吐:已經(jīng)在 Yahoo 的生產(chǎn)環(huán)境中經(jīng)受了考驗,支持每秒數(shù)百萬消息的 發(fā)布-訂閱(Pub-Sub)
低延遲:在大規(guī)模的消息量下依然能夠保持低延遲(小于 5 ms)
持久化機制:Plusar 的持久化機制構(gòu)建在 Apache BookKeeper 上,提供了讀寫分離
讀寫分離:BookKeeper 的讀寫分離 IO 模型極大發(fā)揮了磁盤順序?qū)懶阅?,對機械硬盤相對比較友好,單臺 bookie 節(jié)點支撐的 topic 數(shù)不受限制
Apache Pulsar 的架構(gòu)設(shè)計解決了我們使用 Kafka 過程中遇到的各種問題,并且提供了很多非常棒的特性,如多租戶、消息隊列和批流融合的消費模型、強一致性等。
為了進一步加深對 Apache Pulsar 的理解,衡量 Pulsar 能否真正滿足我們生產(chǎn)環(huán)境大規(guī)模消息 Pub-Sub 的需求,我們從 2019 年 12 月份開始進行了一系列壓測工作。由于我們使用的是機械硬盤,沒有 SSD,在壓測過程中遇到了一些列性能問題,非常感謝 StreamNative 同學(xué)的幫助,感謝斯杰、翟佳、鵬輝的耐心指導(dǎo)和探討,經(jīng)過一系列的性能調(diào)優(yōu),不斷提高 Pulsar 的吞吐和穩(wěn)定性。
經(jīng)過 3~4 個月的壓測和調(diào)優(yōu),2020 年 4 月份我們正式在生產(chǎn)環(huán)境中使用 Pulsar 集群。我們采用 bookie 和 broker 在同一個節(jié)點的混部模式,逐步替換生產(chǎn)環(huán)境的 Kafka 集群。截止到目前為止,生產(chǎn)環(huán)境中 Pulsar 集群規(guī)模為十幾臺,日處理消息量為百億級別,并且正在逐步擴容和遷移 Kafka 流量到 Pulsar 集群。
大家在使用/壓測 Pulsar 時,可能會遇到如下問題:
Pulsar broker 節(jié)點負載不均衡。
Pulsar broker 端 Cache 命中率低,導(dǎo)致大量讀請求進入 bookie,且讀性能比較差。
壓測時經(jīng)常出現(xiàn) broker 內(nèi)存溢出現(xiàn)象(OOM)。
Bookie 出現(xiàn) direct memory OOM 導(dǎo)致進程掛掉。
Bookie 節(jié)點負載不均衡,且經(jīng)常抖動。
當 Journal 盤為 HDD 時,雖然關(guān)閉了 fsync,但是 bookie add entry 99th latency 依舊很高,寫入性能較差。
當 bookie 中有大量讀請求時,出現(xiàn)寫被反壓,add entry latency 上升。
Pulsar client 經(jīng)常出現(xiàn)“Lookup Timeout Exception”。
ZooKeeper 讀寫延遲過高導(dǎo)致整個 Pulsar 集群不穩(wěn)定。
使用 reader API(eg. pulsar flink connector) 消費 Pulsar topic 時,消費速度較慢(Pulsar 2.5.2 之前版本)。
當 Journal/Ledger 盤為機械硬盤(HDD)時,問題 4、5、6、7 表現(xiàn)得尤為嚴重。這些問題直觀來看,是磁盤不夠快造成的,如果 Journal/Ledger 盤讀寫速度足夠快,就不會出現(xiàn)消息在 direct memory 中堆積,也就不會有一系列 OOM 的發(fā)生。
由于在我們消息隊列生產(chǎn)系統(tǒng)中,需要存儲的數(shù)據(jù)量比較大(TB ~ PB 級別),Journal 盤和 Ledger 盤都是 SSD 需要較高的成本,那么有沒有可能在 Pulsar / BookKeeper 上做一些參數(shù)/策略的優(yōu)化,讓 HDD 也能發(fā)揮出較好的性能呢?
在壓測和使用 Pulsar 過程中,我們遇到了一系列性能問題,主要分為 Pulsar Broker 層面和 BookKeeper 層面。為此,本系列性能調(diào)優(yōu)文章分為兩篇,分別介紹 BIGO 在使用 Pulsar 過程中對 Pulsar Broker 和 Bookkeeper 進行性能調(diào)優(yōu)的解決方案,以使得 Pulsar 無論在磁盤為 SSD 還是 HDD 場景下,都能獲得比較好的性能。
由于篇幅原因,本次性能調(diào)優(yōu)系列分為兩部分,上半部分主要介紹 Pulsar broker 的性能調(diào)優(yōu),下半部分主要介紹 BookKeeper 與 Pulsar 結(jié)合過程中的性能調(diào)優(yōu)。
接下來主要介紹 Pulsar / BookKeeper 中和性能相關(guān)的部分,并提出一些性能調(diào)優(yōu)的建議(這些性能調(diào)優(yōu)方案已經(jīng)在 BIGO 生產(chǎn)系統(tǒng)中穩(wěn)定運行,并獲得了不錯的收益)。
由于 BookKeeper 和 Pulsar Broker 重度依賴 ZooKeeper,為了保證 Pulsar 的穩(wěn)定,需要保證 ZooKeeper Read/Write 低延遲。此外,BookKeeper 是 IO 密集型任務(wù),為了避免 IO 之間互相干擾,Journal/Ledger 放在獨立磁盤上??偨Y(jié)如下:
Bookie Journal/Ledger 目錄放在獨立磁盤上
當 Journal/Ledger 目錄的磁盤為 HDD 時,ZooKeeper dataDir/dataLogDir 不要和 Journal/Ledger 目錄放在同一塊磁盤上
BookKeeper 和 Pulsar Broker 均依賴 direct memory,而且 BookKeeper 還依賴 PageCache 進行數(shù)據(jù)讀寫加速,所以合理的內(nèi)存分配策略也是至關(guān)重要的。Pulsar 社區(qū)的 sijie 推薦的內(nèi)存分配策略如下:
OS: 1 ~ 2 GB
JVM: 1/2
heap: 1/3
direct memory: 2/3
PageCache: 1/2
假設(shè)機器物理內(nèi)存為 128G,bookie 和 broker 混部,內(nèi)存分配如下:
OS: 2GB
Broker: 31GB
heap: 10GB
direct memory: 21GB
Bookie: 32GB
heap: 10GB
direct memory: 22GB
PageCache: 63GB
為了更加直觀地發(fā)現(xiàn)系統(tǒng)性能瓶頸,我們需要為 Pulsar/BookKeeper 搭建一套完善的監(jiān)控體系,確保每一個環(huán)節(jié)都有相關(guān)指標上報,當出現(xiàn)異常(包括但不限于性能問題)時,能夠通過相關(guān)監(jiān)控指標快速定位性能瓶頸,并制定相應(yīng)解決方案。
Pulsar/BookKeeper 都提供了 Prometheus 接口,相關(guān)統(tǒng)計指標可以直接使用 Http 方式獲取并直接對接 Prometheus/Grafana。感興趣的同學(xué)可以直接按照 Pulsar Manager 的指導(dǎo)進行安裝: https://github.com/streamnative/pulsar-manager。
需要重點關(guān)注的指標如下:
Pulsar Broker
jvm heap/gc
bytes in per broker
message in per broker
loadbalance
broker 端 Cache 命中率
bookie client quarantine ratio
bookie client request queue
BookKeeper
bookie request queue size
bookie request queue wait time
add entry 99th latency
read entry 99th latency
journal create log latency
ledger write cache flush latency
entry read throttle
ZooKeeper
local/global ZooKeeper read/write request latency
有一些指標在上面 repo 中沒有提供相應(yīng) Grafana 模板,大家可以自己添加 PromQL 進行配置。
對 Pulsar broker 的性能調(diào)優(yōu),主要分為如下幾個方面:
Broker 之間負載均衡
Bookie 節(jié)點之間的負載均衡
限流
Broker 接收消息需要做流控,防止突發(fā)洪峰流量導(dǎo)致 broker direct memory OOM。
Broker 發(fā)送消息給 consumer/reader 時需要做流控,防止一次發(fā)送太多消息造成 consumer/reader 頻繁 GC。
提高 Cache 命中率
保證 ZooKeeper 讀寫低延遲
關(guān)閉 auto bundle split,保證系統(tǒng)穩(wěn)定
Broker 之間負載均衡,能夠提高 broker 節(jié)點的利用率,提高 Broker Cache 命中率,降低 broker OOM 概率。這一部分內(nèi)容主要涉及到 Pulsar bundle rebalance 相關(guān)知識。
Namespace Bundle 結(jié)構(gòu)如下,每個 namespace(命名空間)由一定數(shù)量的 bundle 組成,該 namespace 下的所有 topic 均通過 hash 方式映射到唯一 bundle 上,然后 bundle 通過 load/unload 方式加載/卸載到提供服務(wù)的 broker 上。
如果某個 broker 上沒有 bundle 或者 bundle 數(shù)量比其他 broker 少,那么這臺 broker 的流量就會比其他 broker 低。
現(xiàn)有的/默認的 bundle rebalance 策略(OverloadShedder)為:每隔一分鐘統(tǒng)計集群中所有 broker 的 CPU、Memory、Direct Memory、BindWith In、BindWith Out 占用率的最大值是否超過閾值(默認為85%);如果超過閾值,則將一定數(shù)量大入流量的 bundle 從該 broker 中卸載掉,然后由 leader 決定將被卸載掉的 bundle 重新加載到負載最低的 broker 上。
這個策略存在的問題是:
默認閾值比較難達到,很容易導(dǎo)致集群中大部分流量都集中在幾個 broker 上;
閾值調(diào)整標準難以確定,受其他因素影響較大,特別是這個節(jié)點上部署有其他服務(wù)的情況下;
broker 重啟后,長時間沒有流量均衡到該 broker 上,因為其他 broker 節(jié)點均沒有達到 bundle unload 閾值。
為此,我們開發(fā)了一個基于均值的負載均衡策略,并支持 CPU、Memory、Direct Memory、BindWith In、BindWith Out 權(quán)重配置,相關(guān)策略請參見 PR-6772。
該策略在 Pulsar 2.6.0 版本開始支持,默認關(guān)閉,可以在 broker.conf 中修改如下參數(shù)開啟:
loadBalancerLoadSheddingStrategy=org.apache.pulsar.broker.loadbalance.impl.ThresholdShedder
我們可以通過如下參數(shù)來精確控制不同采集指標的權(quán)重:
# The broker resource usage threshold. # When the broker resource usage is greater than the pulsar cluster average resource usage, # the threshold shredder will be triggered to offload bundles from the broker. # It only takes effect in ThresholdSheddler strategy. loadBalancerBrokerThresholdShedderPercentage=10 # When calculating new resource usage, the history usage accounts for. # It only takes effect in ThresholdSheddler strategy. loadBalancerHistoryResourcePercentage=0.9 # The BandWithIn usage weight when calculating new resource usage. # It only takes effect in ThresholdShedder strategy. loadBalancerBandwithInResourceWeight=1.0 # The BandWithOut usage weight when calculating new resource usage. # It only takes effect in ThresholdShedder strategy. loadBalancerBandwithOutResourceWeight=1.0 # The CPU usage weight when calculating new resource usage. # It only takes effect in ThresholdShedder strategy. loadBalancerCPUResourceWeight=1.0 # The heap memory usage weight when calculating new resource usage. # It only takes effect in ThresholdShedder strategy. loadBalancerMemoryResourceWeight=1.0 # The direct memory usage weight when calculating new resource usage. # It only takes effect in ThresholdShedder strategy. loadBalancerDirectMemoryResourceWeight=1.0 # Bundle unload minimum throughput threshold (MB), avoiding bundle unload frequently. # It only takes effect in ThresholdShedder strategy. loadBalancerBundleUnloadMinThroughputThreshold=10
Bookie 節(jié)點負載監(jiān)控如下圖所示,我們會發(fā)現(xiàn):
Bookie 節(jié)點之間負載并不是均勻的,最高流量節(jié)點和最低流量節(jié)點可能相差幾百 MB/s
在高負載情況下,某些節(jié)點的負載可能會出現(xiàn)周期性上漲和下降,周期為 30 分鐘
這些問題的影響是:bookie 負載不均衡,導(dǎo)致 BookKeeper 集群利用率下降,且容易出現(xiàn)抖動。
出現(xiàn)這個問題的原因在于:bookie client 對 bookie 寫請求的熔斷策略粒度太大。
先來回顧一下 Pulsar broker 寫入 bookie 的策略:
當 broker 接收到 producer 發(fā)送的 message 時,首先會將消息存放在 broker 的 direct memory 中,然后調(diào)用 bookie client 根據(jù)配置的(EnsembleSize,WriteQuorum,AckQuorum)策略將 message 以 pipeline 方式發(fā)送給 bookies。
Bookie client 每分鐘會統(tǒng)計各 bookie 寫入的失敗率(包括寫超時等各類異常)。默認情況下,當失敗率超過 5 次/分鐘時,這臺 bookie 將會被關(guān)入小黑屋 30 分鐘,避免持續(xù)向出現(xiàn)異常的 bookie 寫入數(shù)據(jù),從而保證 message 寫入成功率。
這個熔斷策略存在的問題是:某臺 bookie 負載(流量)很高時,所有寫入到該 bookie 的消息有可能同時會變慢,所有 bookie client 可能同時收到寫入異常,如寫入超時等,那么所有 bookie client 會同時把這臺 bookie 關(guān)入小黑屋 30 分鐘,等到 30 分鐘之后又同時加入可寫入列表中。這就導(dǎo)致了這臺 bookie 的負載周期性上漲和下降。
為了解決該問題,我們引入了基于概率的 quarantine 機制,當 bookie client 寫入消息出現(xiàn)異常時,并不是直接將這臺 bookie 關(guān)入小黑屋,而是基于概率決定是否 quarantine。
這一 quarantine 策略可以避免所有 bookie client 同時將同一臺 bookie 關(guān)入小黑屋,避免 bookie 入流量抖動。相關(guān) PR 請參見:BookKeeper PR-2327 ,由于代碼沒有合并和發(fā)布到 bookie 主版本,大家如果想使用該功能,需要自己獨立編譯代碼:https://github.com/apache/bookkeeper/pull/2327。
從 BIGO 實踐測試來看,該功能將 bookie 節(jié)點之間入流量標準差從 75 MB/s 降低到 40 MB/s。
在生產(chǎn)環(huán)境中,在高吞吐場景下,我們經(jīng)常遇到 broker direct memory OOM,導(dǎo)致 broker 進程掛掉。這里的原因可能是底層 bookie 寫入變慢,導(dǎo)致大量數(shù)據(jù)積壓在 broker direct memory 中。Producer 發(fā)送的消息在 broker 中的處理過程如下圖所示:
在生產(chǎn)環(huán)境中,我們不能保證底層 bookie 始終保持非常低的寫延遲,所以需要在 broker 層做限流。Pulsar 社區(qū)的鵬輝開發(fā)了限流功能,限流邏輯如下圖所示:
在 Pulsar 2.5.1 版本中已發(fā)布,請參見 PR-6178。
當 producer 端以 batch 模式發(fā)送消息時,consumer 端往往會占用過多內(nèi)存導(dǎo)致頻繁 GC,監(jiān)控上的表現(xiàn)是:這個 topic 的負載在 consumer 啟動時飆升,然后逐漸回歸到正常水平。
這個問題的原因需要結(jié)合 consumer 端的消費模式來看。
當 consumer 調(diào)用 receive 接口消費一條消息時,它會直接從本地的 receiverQueue 中請求一條消息,如果 receiverQueue 中還有消息可以獲取,則直接將消息返回給 consumer 端,并更新 availablePermit,當 availablePermit < receiverQueueSize/2 時,Pulsar client 會將 availablePermit 發(fā)送給 broker,告訴 broker 需要 push 多少條消息過來;如果 receiverQueue 中沒有消息可以獲取,則等待/返回失敗,直到 receiverQueue 收到 broker 推送的消息才將 consumer 喚醒。
Broker 收到 availablePermit 之后,會從 broker Cache/bookie 中讀取 max(availablePermit, batchSize)
條 entry,并發(fā)送給 consumer 端。處理邏輯如下圖所示:
這里的問題是:當 producer 開啟 batch 模式發(fā)送,一個 entry 包含多條消息,但是 broker 處理 availablePermit 請求仍然把一條消息作為一個 entry 來處理,從而導(dǎo)致 broker 一次性將大量信息發(fā)送給 consumer,這些消息數(shù)量遠遠超過 availiablePermit(availiablePermit vs. availiablePermit * batchSize)的接受能力,引起 consumer 占用內(nèi)存暴漲,引發(fā)頻繁 GC,降低消費性能。
為了解決 consumer 端內(nèi)存暴漲問題,我們在 broker 端統(tǒng)計每個 topic 平均 entry 包含的消息數(shù)(avgMessageSizePerEntry), 當接收到 consumer 請求的 availablePermit 時,將其換算成需要發(fā)送的 entry 大小,然后從 broker Cache/bookie 中拉取相應(yīng)數(shù)量的 entry,然后發(fā)送給 consumer。處理邏輯如下圖所示:
這個功能在 Pulsar 2.6.0 中已發(fā)布,默認是關(guān)閉的,大家可以通過如下開關(guān)啟用該功能:
# Precise dispatcher flow control according to history message number of each entry preciseDispatcherFlowControl=true
Pulsar 中有多層 Cache 提升 message 的讀性能,主要包括:
Broker Cache
Bookie write Cache(Memtable)
Bookie read Cache
OS PageCache
本章主要介紹 broker Cache 的運行機制和調(diào)優(yōu)方案,bookie 側(cè)的 Cache 調(diào)優(yōu)放在下篇介紹。
當 broker 收到 producer 發(fā)送給某個 topic 的消息時,首先會判斷該 topic 是否有 Active Cursor,如果有,則將收到的消息寫入該 topic 對應(yīng)的 Cache 中;否則,不寫入 Cache。處理流程如下圖所示:
判斷是否有 Active Cursor 需要同時滿足以下兩個條件:
有 durable cursor
Cursor 的 lag 在 managedLedgerCursorBackloggedThreshold 范圍內(nèi)
由于 reader 使用 non-durable cursor 進行消費,所以 producer 寫入的消息不會進入 broker Cache,從而導(dǎo)致大量請求落到 bookie 上,性能有所損耗。
streamnative/pulsar-flink-connector 使用的是 reader API 進行消費,所以同樣存在消費性能低的問題。
我們 BIGO 消息隊列團隊的趙榮生同學(xué)修復(fù)了這個問題,將 durable cursor 從 Active Cursor 判斷條件中刪除,詳情請見 PR-6769 ,這個 feature 在 Pulsar 2.5.2 發(fā)布,有遇到相關(guān)性能問題的同學(xué)請升級 Pulsar 版本到 2.5.2 以上。
此外,我們針對 topic 的每個 subscription 添加了 Cache 命中率監(jiān)控,方便進行消費性能問題定位,后續(xù)會貢獻到社區(qū)。
對于已經(jīng)在 broker Cache 中的數(shù)據(jù),在 tailing read 場景下,我們怎樣提高 Cache 命中率,降低從 bookie 讀取數(shù)據(jù)的概率呢?我們的思路是盡可能讓數(shù)據(jù)從 broker Cache 中讀取,為了保證這一點,我們從兩個地方著手優(yōu)化:
控制判定為 Active Cursor 的最大 lag 范圍,默認是 1000 個 entry ,由如下參數(shù)控:
# Configure the threshold (in number of entries) from where a cursor should be considered 'backlogged' # and thus should be set as inactive. managedLedgerCursorBackloggedThreshold=1000
Active Cursor 的判定如下圖所示。
控制 broker Cache 的 eviction 策略,目前 Pulsar 中只支持默認 eviction 策略,有需求的同學(xué)可以自行擴展。默認 eviction 策略由如下參數(shù)控制:
# Amount of memory to use for caching data payload in managed ledger. This memory # is allocated from JVM direct memory and it's shared across all the topics # running in the same broker. By default, uses 1/5th of available direct memory managedLedgerCacheSizeMB= # Whether we should make a copy of the entry payloads when inserting in cache managedLedgerCacheCopyEntries=false # Threshold to which bring down the cache level when eviction is triggered managedLedgerCacheEvictionWatermark=0.9 # Configure the cache eviction frequency for the managed ledger cache (evictions/sec) managedLedgerCacheEvictionFrequency=100.0 # All entries that have stayed in cache for more than the configured time, will be evicted managedLedgerCacheEvictionTimeThresholdMillis=1000
對于 Catchup Read 場景,broker Cache 大概率會丟失,所有的 read 請求都會落到 bookie 上,那么有沒有辦法提高讀 bookie 的性能呢?
Broker 向 bookie 批量發(fā)送讀取請求,最大 batch 由 dispatcherMaxReadBatchSize 控制,默認是 100 個 entry。
# Max number of entries to read from bookkeeper. By default it is 100 entries. dispatcherMaxReadBatchSize=100
一次讀取的 batchSize 越大,底層 bookie 從磁盤讀取的效率越高,均攤到單個 entry 的 read latency 就越低。但是如果過大也會造成 batch 讀取延遲增加,因為底層 bookie 讀取操作時每次讀一條 entry,而且是同步讀取。
這一部分的讀取調(diào)優(yōu)放在《Apache Pulsar 在 BIGO 的性能調(diào)優(yōu)實戰(zhàn)(下)》中介紹。
由于 Pulsar 和 BookKeeper 都是嚴重依賴 ZooKeeper 的,如果 ZooKeeper 讀寫延遲增加,就會導(dǎo)致 Pulsar 服務(wù)不穩(wěn)定。所以需要優(yōu)先保證 ZooKeeper 讀寫低延遲。建議如下:
在磁盤為 HDD 情況下,ZooKeeper dataDir/dataLogDir 不要和其他消耗 IO 的服務(wù)(如 bookie Journal/Ledger 目錄)放在同一塊盤上(SSD 除外);
ZooKeeper dataDir 和 dataLogDir 最好能夠放在兩塊獨立磁盤上(SSD 除外);
監(jiān)控 broker/bookie 網(wǎng)卡利用率,避免由于網(wǎng)卡打滿而造成和 ZooKeeper 失聯(lián)。
Pulsar bundle split 是一個比較耗費資源的操作,會造成連接到這個 bundle 上的所有 producer/consumer/reader 連接斷開并重連。一般情況下,觸發(fā) auto bundle split
的原因是這個 bundle 的壓力比較大,需要切分成兩個 bundle,將流量分攤到其他 broker,來降低這個 bundle 的壓力??刂?auto bundle split 的參數(shù)如下:
# enable/disable namespace bundle auto split loadBalancerAutoBundleSplitEnabled=true # enable/disable automatic unloading of split bundles loadBalancerAutoUnloadSplitBundlesEnabled=true # maximum topics in a bundle, otherwise bundle split will be triggered loadBalancerNamespaceBundleMaxTopics=1000 # maximum sessions (producers + consumers) in a bundle, otherwise bundle split will be triggered loadBalancerNamespaceBundleMaxSessions=1000 # maximum msgRate (in + out) in a bundle, otherwise bundle split will be triggered loadBalancerNamespaceBundleMaxMsgRate=30000 # maximum bandwidth (in + out) in a bundle, otherwise bundle split will be triggered loadBalancerNamespaceBundleMaxBandwidthMbytes=100
當觸發(fā) auto bundle split 時 broker 負載比較高,關(guān)閉這個 bundle 上的 producer/consumer/reader,連接就會變慢,并且 bundle split 的耗時也會變長,就很容易造成 client 端(producer/consumer/reader)連接超時而失敗,觸發(fā) client 端自動重連,造成 Pulsar/Pulsar client 不穩(wěn)定。
對于生產(chǎn)環(huán)境,我們的建議是:預(yù)先為每個 namespace 分配好 bundle 數(shù),并關(guān)閉 auto bundle split 功能。如果在運行過程中發(fā)現(xiàn)某個 bundle 壓力過大,可以在流量低峰期進行手動 bundle split,降低對 client 端的影響。
關(guān)于預(yù)先分配的 bundle 數(shù)量不宜太大,bundle 數(shù)太多會給 ZooKeeper 造成比較大的壓力,因為每一個 bundle 都要定期向 ZooKeeper 匯報自身的統(tǒng)計數(shù)據(jù)。
看完上述內(nèi)容,你們掌握Apache Pulsar在BIGO的性能調(diào)優(yōu)實戰(zhàn)是怎樣的的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!