摘要:主機(jī)監(jiān)控個(gè)人認(rèn)為對(duì)于主機(jī)的監(jiān)控是最重要的。在實(shí)際監(jiān)控時(shí)可以有意識(shí)地驗(yàn)證這一點(diǎn)。另外還有兩個(gè)線程池空閑使用率小關(guān)注,最好確保它們的值都不要低于,否則說(shuō)明已經(jīng)非常的繁忙。此時(shí)需要調(diào)整線程池線程數(shù)。
胡夕,《Apache Kafka實(shí)戰(zhàn)》作者,北航計(jì)算機(jī)碩士畢業(yè),現(xiàn)任某互金公司計(jì)算平臺(tái)總監(jiān),曾就職于IBM、搜狗、微博等公司。國(guó)內(nèi)活躍的Kafka代碼貢獻(xiàn)者。
前言
雖然目前Apache Kafka已經(jīng)全面進(jìn)化成一個(gè)流處理平臺(tái),但大多數(shù)的用戶依然使用的是其核心功能:消息隊(duì)列。對(duì)于如何有效地監(jiān)控和調(diào)優(yōu)Kafka是一個(gè)大話題,很多用戶都有這樣的困擾,今天我們就來(lái)討論一下。
一、Kafka綜述
在討論具體的監(jiān)控與調(diào)優(yōu)之前,我想用一張PPT圖來(lái)簡(jiǎn)單說(shuō)明一下當(dāng)前Kafka生態(tài)系統(tǒng)的各個(gè)組件。就像我前面所說(shuō),Kafka目前已經(jīng)進(jìn)化成了一個(gè)流處理平臺(tái),除了核心的消息隊(duì)列組件Kafka core之外,社區(qū)還新引入Kafka Connect和Kafka Streams兩個(gè)新的組件:其中前者負(fù)責(zé)Kafka與外部系統(tǒng)的數(shù)據(jù)傳輸;后者則負(fù)責(zé)對(duì)數(shù)據(jù)進(jìn)行實(shí)時(shí)流處理計(jì)算。下圖羅列了一些關(guān)鍵的Kafka概念。
二、Kafka監(jiān)控
我打算從五個(gè)維度來(lái)討論Kafka的監(jiān)控。首先是要監(jiān)控Kafka集群所在的主機(jī);第二是監(jiān)控Kafka broker JVM的表現(xiàn);第三點(diǎn),我們要監(jiān)控Kafka Broker的性能;第四,我們要監(jiān)控Kafka客戶端的性能。這里的所指的是廣義的客戶端——可能是指我們自己編寫的生產(chǎn)者、消費(fèi)者,也有可能是社區(qū)幫我們提供的生產(chǎn)者、消費(fèi)者,比如說(shuō)Connect的Sink/Source或Streams等;最后我們需要監(jiān)控服務(wù)器之間的交互行為。
1.主機(jī)監(jiān)控
個(gè)人認(rèn)為對(duì)于主機(jī)的監(jiān)控是最重要的。因?yàn)楹芏嗑€上環(huán)境問(wèn)題首先表現(xiàn)出來(lái)的癥狀就是主機(jī)的某些性能出現(xiàn)了明顯的問(wèn)題。此時(shí)通常是運(yùn)維人員首先發(fā)現(xiàn)了它們?nèi)缓蟾嬖V我們這臺(tái)機(jī)器有什么問(wèn)題,對(duì)于Kafka主機(jī)監(jiān)控通常是發(fā)現(xiàn)問(wèn)題的第一步。這一頁(yè)列出了常見(jiàn)的指標(biāo),包括CPU、內(nèi)存、帶寬等數(shù)據(jù)。需要注意的是CPU使用率的統(tǒng)計(jì)??赡艽蠹衣犨^(guò)這樣的提法:我的Kafka Broker CPU使用率是400%,怎么回事?對(duì)于這樣的問(wèn)題,我們首先要搞清楚這個(gè)使用率是怎么觀測(cè)出來(lái)的? 很多人拿top命令中的vss或rss字段來(lái)表征CPU使用率,但實(shí)際上它們并不是真正的CPU使用率——那只是所有CPU共同作用于Kafka進(jìn)程所花的時(shí)間片的比例。舉個(gè)例子,如果機(jī)器上有16個(gè)CPU,那么只要這些值沒(méi)有超過(guò)或接近1600, 那么你的CPU使用率實(shí)際上是很低的。因此要正確理解這些命令中各個(gè)字段的含義。
這頁(yè)P(yáng)PT右邊給出了一本書,如果大家想監(jiān)控主機(jī)性能的話,我個(gè)人建議這本《SystemsPerformance》就足夠了。非常權(quán)威的一本書,推薦大家讀一下。
2.監(jiān)控JVM
Kafka本身是一個(gè)普通的Java進(jìn)程,所以任何適用于JVM監(jiān)控的方法對(duì)于監(jiān)控Kafka都是相通的。第一步就是要先了解Kafka應(yīng)用。比方說(shuō)了解Kafka broker JVM的GC頻率和延時(shí)都是多少,每次GC后存活對(duì)象的大小是怎樣的等。了解了這些信息我們才能明確后面調(diào)優(yōu)的方向。當(dāng)然,我們畢竟不是特別資深的JVM專家,因此也不必過(guò)多追求繁復(fù)的JVM監(jiān)控與調(diào)優(yōu)。只需要關(guān)注大的方面即可。另外,如果大家時(shí)間很有限但又想快速掌握J(rèn)VM監(jiān)控與調(diào)優(yōu),推薦閱讀《Java Performance》。
3.Per-Broker監(jiān)控
首先要確保Broker進(jìn)程是啟動(dòng)狀態(tài)?這聽起來(lái)好像有點(diǎn)搞笑,但我的確遇到過(guò)這樣的情況。比如當(dāng)把Kafka部署在Docker上時(shí)就容易出現(xiàn)進(jìn)程啟動(dòng)但服務(wù)沒(méi)有成功啟動(dòng)的情形。正常啟動(dòng)下,一個(gè)Kafka服務(wù)器起來(lái)的時(shí)候,應(yīng)該有兩個(gè)端口,一個(gè)端口是9092常規(guī)端口,會(huì)建一個(gè)TCP鏈接。還有一個(gè)端口是給JMX監(jiān)控用的。當(dāng)然有多臺(tái)broker的話,那么controller機(jī)器會(huì)為每臺(tái)broker都維護(hù)一個(gè)TCP連接。在實(shí)際監(jiān)控時(shí)可以有意識(shí)地驗(yàn)證這一點(diǎn)。
對(duì)于Broker的監(jiān)控,我們主要是通過(guò)JMS指標(biāo)來(lái)做的。用過(guò)Kafka的人知道,Kafka社區(qū)提供了特別多的JMS指標(biāo),其中很多指標(biāo)用處不大。我這里列了一些比較重要的:首先是broker機(jī)器每秒出入的字節(jié)數(shù),就是類似于我可以監(jiān)控網(wǎng)卡的流量,一定要把這個(gè)指標(biāo)監(jiān)控起來(lái),并實(shí)時(shí)與你的網(wǎng)卡帶寬進(jìn)行比較——如果發(fā)現(xiàn)該值非常接近于帶寬的話,就證明broker負(fù)載過(guò)高,要么增加新的broker機(jī)器,要么把該broker上的負(fù)載均衡到其他機(jī)器上。
另外還有兩個(gè)線程池空閑使用率小關(guān)注,最好確保它們的值都不要低于30%,否則說(shuō)明Broker已經(jīng)非常的繁忙。 此時(shí)需要調(diào)整線程池線程數(shù)。
接下來(lái)是監(jiān)控broker服務(wù)器的日志。日志中包含了非常豐富的信息。這里所說(shuō)的日志不僅是broker服務(wù)器的日志,還包括Kafka controller的日志。我們需要經(jīng)常性地查看日志中是否出現(xiàn)了OOM錯(cuò)誤抑或是時(shí)刻關(guān)注日志中拋出的ERROR信息。
我們還需要監(jiān)控一些關(guān)鍵后臺(tái)線程的運(yùn)行狀態(tài)。個(gè)人認(rèn)為有兩個(gè)比較重要的線程需要監(jiān)控:一個(gè)Log Cleaner線程——該線程是執(zhí)行數(shù)據(jù)壓實(shí)操作的,如果該線程出問(wèn)題了,用戶通常無(wú)法感知到,然后會(huì)發(fā)現(xiàn)所有compact策略的topic會(huì)越來(lái)越大直到占滿所有磁盤空間;另一個(gè)線程就是副本拉取線程,即follower broker使用該線程實(shí)時(shí)從leader處拉取數(shù)據(jù)。如果該線程“掛掉”了,用戶通常也是不知道的,但會(huì)發(fā)現(xiàn)follower不再拉取數(shù)據(jù)了。因此我們一定要定期地查看這兩個(gè)線程的狀態(tài),如果發(fā)現(xiàn)它們意味終止,則去找日志中尋找對(duì)應(yīng)的報(bào)錯(cuò)信息。
4.Clients監(jiān)控
客戶端監(jiān)控這塊,我這邊會(huì)分為兩個(gè),分別討論對(duì)生產(chǎn)者和消費(fèi)者的監(jiān)控。生產(chǎn)者往Kafka發(fā)消息,在監(jiān)控之前我們至少要了解一下客戶端機(jī)器與Broker端機(jī)器之間的RTT是多少。對(duì)于那種跨數(shù)據(jù)中心或者是異地的情況來(lái)說(shuō),RTT本來(lái)就很大,如果不做特殊的調(diào)優(yōu),是不可能有太高的TPS的。目前Kafka producer是雙線程的設(shè)計(jì)機(jī)制,分為用戶主線程和Sender線程,當(dāng)這個(gè)Sender線程掛了的時(shí)候,前端用戶是不感知的,但表現(xiàn)為producer發(fā)送消息失敗,所以用戶最好監(jiān)控一下這個(gè)Sender線程的狀態(tài)。
還有就是監(jiān)控PRODUCE請(qǐng)求的處理延時(shí)。一條消息從生產(chǎn)者端發(fā)送到Kafka broker進(jìn)行處理,之后返回給producer的總時(shí)間。整個(gè)鏈路中各個(gè)環(huán)節(jié)的耗時(shí)最好要做到心中有數(shù)。因?yàn)楹芏嗲闆r下,如果你要提升生產(chǎn)者的TPS,了解整個(gè)鏈路中的瓶頸后才能做到有的放矢。后面PPT中我會(huì)討論如何拆解這條鏈路。
現(xiàn)在說(shuō)說(shuō)消費(fèi)者。這里的消費(fèi)者說(shuō)的是新版本的消費(fèi)者,也就是java consumer。
社區(qū)已經(jīng)非常不推薦再繼續(xù)使用老版本的消費(fèi)者了。新版本的消費(fèi)者也是雙線程設(shè)計(jì),后面有一個(gè)心跳線程,如果這個(gè)線程掛掉的話,前臺(tái)線程是不知情的。所以,用戶最好定期監(jiān)控該心跳線程的存活情況。心跳線程定期發(fā)心跳請(qǐng)求給Kafka服務(wù)器,告訴Kafka,這個(gè)消費(fèi)者實(shí)例還活著,以避免coordinator錯(cuò)誤地認(rèn)為此實(shí)例已“死掉”從而開啟rebalance。Kafka提供了很多的JMX指標(biāo)可以用于監(jiān)控消費(fèi)者,最重要的消費(fèi)進(jìn)度滯后監(jiān)控,也就是所謂的consumerlag。
假設(shè)producer生產(chǎn)了100條消息,消費(fèi)者讀取了80條,那么lag就是20。顯然落后的越少越好,這表明消費(fèi)者非常及時(shí),用戶也可以用工具行命令來(lái)查lag,甚至寫Java的API來(lái)查。與lag對(duì)應(yīng)的還有一個(gè)lead指標(biāo),它表征的是消費(fèi)者領(lǐng)先第一條消息的進(jìn)度。比如最早的消費(fèi)位移是1,如果消費(fèi)者當(dāng)前消費(fèi)的消息是10,那么lead就是9。對(duì)于lead而言越大越好,否則表明此消費(fèi)者可能處于停頓狀態(tài)或者消費(fèi)的非常慢,本質(zhì)上lead和lag是一回事,之所以列出來(lái)是因?yàn)閘ead指標(biāo)是我開發(fā)的,也算打個(gè)廣告吧。
除了以上這些,我們還需要監(jiān)控消費(fèi)者組的分區(qū)分配情況,避免出現(xiàn)某個(gè)實(shí)例被分配了過(guò)多的分區(qū),導(dǎo)致負(fù)載嚴(yán)重不平衡的情況出現(xiàn)。一般來(lái)說(shuō),如果組內(nèi)所有消費(fèi)者訂閱的是相同的主題,那么通常不會(huì)出現(xiàn)明顯的分配傾斜。一旦各個(gè)實(shí)例訂閱的主題不相同且每個(gè)主題分區(qū)數(shù)參差不齊時(shí)就極易發(fā)生這種不平衡的情況。Kafka目前提供了3種策略來(lái)幫助用戶完成分區(qū)分配,最新的策略是黏性分配策略,它能保證絕對(duì)的公平,大家可以去試一下。
最后就是要監(jiān)控rebalance的時(shí)間——目前來(lái)看,組內(nèi)超多實(shí)例的rebalance性能很差,可能都是小時(shí)級(jí)別的。而且比較悲劇的是當(dāng)前無(wú)較好的解決方案。所以,如果你的Consumer特別特別多的話,一定會(huì)有這個(gè)問(wèn)題,你監(jiān)控一下兩個(gè)步驟所用的時(shí)間,看看是否滿足需求,如果不能滿足的話,看看能不能把消費(fèi)者去除,盡量減少消費(fèi)者數(shù)量。
5.Inter-Broker監(jiān)控
最后一個(gè)維度就是監(jiān)控Broker之間的表現(xiàn),主要是指副本拉取。Follower副本實(shí)時(shí)拉取leader處的數(shù)據(jù),我們自然希望這個(gè)拉取過(guò)程越快越好。Kafka提供了一個(gè)特別重要的JMX指標(biāo),叫做備份不足的分區(qū)數(shù),比如說(shuō)我規(guī)定了這條消息,應(yīng)該在三個(gè)Broker上面保存,假設(shè)只有一個(gè)或者兩個(gè)Broker上保存該消息,那么這條消息所在的分區(qū)就被稱為“備份不足”的分區(qū)。這種情況是特別關(guān)注的,因?yàn)橛锌赡茉斐蓴?shù)據(jù)的丟失。《Kafka權(quán)威指南》一書中是這樣說(shuō)的:如果你只能監(jiān)控一個(gè)Kafka JMX指標(biāo),那么就監(jiān)控這個(gè)好了,確保在你的Kafka集群中該值是永遠(yuǎn)是0。一旦出現(xiàn)大于0的情形趕緊處理。
還有一個(gè)比較重要的指標(biāo)是表征controller個(gè)數(shù)的。整個(gè)集群中應(yīng)該確保只能有一臺(tái)機(jī)器的指標(biāo)是1,其他全應(yīng)該是0,如果你發(fā)現(xiàn)有一臺(tái)機(jī)器是2或者是3,一定是出現(xiàn)腦裂了,此時(shí)應(yīng)該去檢查下是否出現(xiàn)了網(wǎng)絡(luò)分區(qū)。Kafka本身是不能對(duì)抗腦裂的,完全依靠Zookeeper來(lái)做,但是如果真正出現(xiàn)網(wǎng)絡(luò)分區(qū)的話,也是沒(méi)有辦法處理的,不如趕快fail fast掉。
三、監(jiān)控工具
當(dāng)前沒(méi)有一款Kafka監(jiān)控工具是公認(rèn)比較優(yōu)秀的,每個(gè)都有自己的特點(diǎn)但也有些致命的缺陷。我們針對(duì)一些常見(jiàn)的監(jiān)控工具逐個(gè)討論下。
1.Kafka Manager
應(yīng)該說(shuō)在所有免費(fèi)的監(jiān)控框架中,Kafka Manager是最受歡迎的。它最早由雅虎開源,功能非常齊全,展示的數(shù)據(jù)非常豐富。另外,用戶能夠在界面上執(zhí)行一些簡(jiǎn)單的集群管理操作。更加令人欣慰的是,該框架目前還在不斷維護(hù)中,因此使用Kafka manager來(lái)監(jiān)控Kafka是一個(gè)不錯(cuò)的選擇。
2.Burrow
Burrow是去年下半年開源,專門監(jiān)控消費(fèi)者信息的框架。這個(gè)框架剛開始開源的時(shí)候,我還對(duì)它還是寄予厚望的,畢竟是Kafka社區(qū)committer親自編寫的。不過(guò)Burrow的問(wèn)題在于沒(méi)有UI界面,不方便運(yùn)維操作。另外由于是Go語(yǔ)言寫的,你要用的話,必須搭建Go語(yǔ)言環(huán)境,然后編譯部署,總之用起來(lái)不是很方便。還有就是它的更新不是很頻繁,已經(jīng)有點(diǎn)半荒廢的狀態(tài),大家不妨一試。
3.Kafka Monitor
嚴(yán)格來(lái)說(shuō),它不是監(jiān)控工具,它是專門做Kafka集群系統(tǒng)性測(cè)試用的。待監(jiān)控的指標(biāo)可以由用戶自己設(shè)定,主要是做一些端到端的測(cè)試。比如說(shuō)你搭了一套Kafka集群,想測(cè)試端到端的性能怎樣:從發(fā)消息到消費(fèi)者讀取消息這一整體流程的性能。該框架的優(yōu)勢(shì)也是由Kafka社區(qū)團(tuán)隊(duì)寫的,質(zhì)量有保障,但更新不是很頻繁,目前好像幾個(gè)月沒(méi)有更新了。
4.Kafka Offset Monitor
KafkaOffsetMonitor是我用的最早的一個(gè)Kafka監(jiān)控工具,也是監(jiān)控消費(fèi)者位移,只不過(guò)那時(shí)候Kafka把位移保持在Zookeepr上。這個(gè)框架的界面非常漂亮,國(guó)內(nèi)用的人很多。但是現(xiàn)在有一個(gè)問(wèn)題,因?yàn)槲覀儸F(xiàn)在用了新版本的消費(fèi)者,這個(gè)框架目前支持得的并不是特別好。而且還有一個(gè)問(wèn)題就是它已經(jīng)不再維護(hù)了,可能有1-2年沒(méi)有任何更新了。
5.Kafka Eagle
這是國(guó)人自己開發(fā)的,我不知道具體是哪個(gè)大牛開發(fā)的,但是在Kafka QQ群里面很多人推崇,因?yàn)榻缑婧芨蓛羝?,上面有很好的?shù)據(jù)展現(xiàn)。
6.Confluent Control Center
Control Center是目前我能收集到的功能最齊全的Kafka監(jiān)控框架了,只不過(guò)只有購(gòu)買了Confluent企業(yè)版也有的,也就是說(shuō)是付費(fèi)的。
綜合來(lái)講,如果你是Kafka集群運(yùn)維操作人員,推薦先用Kafka Manager來(lái)做監(jiān)控,后面再根據(jù)實(shí)際監(jiān)控需求定制化開發(fā)特有的工具或框架。
四、系統(tǒng)調(diào)優(yōu)
Kafka監(jiān)控的一個(gè)主要的目的就是調(diào)優(yōu)Kafka集群。這里羅列了一些常見(jiàn)的操作系統(tǒng)級(jí)的調(diào)優(yōu)。
首先是保證頁(yè)緩存的大小——至少要設(shè)置頁(yè)緩存為一個(gè)日志段的大小。我們知道Kafka大量使用頁(yè)緩存,只要保證頁(yè)緩存足夠大,那么消費(fèi)者讀取消息時(shí)就有大概率保證它能夠直接命中頁(yè)緩存中的數(shù)據(jù)而無(wú)需從底層磁盤中讀取。故只要保證頁(yè)緩存要滿足一個(gè)日志段的大小。
第二是調(diào)優(yōu)文件打開數(shù)。很多人對(duì)這個(gè)資源有點(diǎn)畏手畏腳。實(shí)際上這是一個(gè)很廉價(jià)的資源,設(shè)置一個(gè)比較大的初始值通常都是沒(méi)有什么問(wèn)題的。
第三是調(diào)優(yōu)vm.max_map_count參數(shù)。主要適用于Kafka broker上的主題數(shù)超多的情況。Kafka日志段的索引文件是用映射文件的機(jī)制來(lái)做的,故如果有超多日志段的話,這種索引文件數(shù)必然是很多的,極易打爆這個(gè)資源限制,所以對(duì)于這種情況一般要適當(dāng)調(diào)大這個(gè)參數(shù)。
第四是swap的設(shè)置。很多文章說(shuō)把這個(gè)值設(shè)為0,就是完全禁止swap,我個(gè)人不建議這樣,因?yàn)楫?dāng)你設(shè)置成為0的時(shí)候,一旦你的內(nèi)存耗盡了,Linux會(huì)自動(dòng)開啟OOM killer然后隨機(jī)找一個(gè)進(jìn)程殺掉。這并不是我們希望的處理結(jié)果。相反,我建議設(shè)置該值為一個(gè)比較接近零的較小值,這樣當(dāng)我的內(nèi)存快要耗盡的時(shí)候會(huì)嘗試開啟一小部分swap,雖然會(huì)導(dǎo)致broker變得非常慢,但至少給了用戶發(fā)現(xiàn)問(wèn)題并處理之的機(jī)會(huì)。
第五JVM堆大小。首先鑒于目前Kafka新版本已經(jīng)不支持Java7了,而Java 8本身不更新了,甚至Java9其實(shí)都不做了,直接做Java10了,所以我建議Kafka至少搭配Java8來(lái)搭建。至于堆的大小,個(gè)人認(rèn)為6-10G足矣。如果出現(xiàn)了堆溢出,就提jira給社區(qū),讓他們看到底是怎樣的問(wèn)題。因?yàn)檫@種情況下即使用戶調(diào)大heap size,也只是延緩OOM而已,不太可能從根本上解決問(wèn)題。
最后,建議使用專屬的多塊磁盤來(lái)搭建Kafka集群。自1.1版本起Kafka正式支持JBOD,因此沒(méi)必要在底層再使用一套R(shí)AID了。
五、Kafka調(diào)優(yōu)的四個(gè)層面
Kafka調(diào)優(yōu)通??梢詮?個(gè)維度展開,分別是吞吐量、延遲、持久性和可用性。在具體展開這些方面之前,我想先建議用戶保證客戶端與服務(wù)器端版本一致。如果版本不一致,就會(huì)出現(xiàn)向下轉(zhuǎn)化的問(wèn)題。舉個(gè)例子,服務(wù)器端保存高版本的消息,當(dāng)?shù)桶姹鞠M(fèi)者請(qǐng)求數(shù)據(jù)時(shí),服務(wù)器端就要做轉(zhuǎn)化,先把高版本消息轉(zhuǎn)成低版本再發(fā)送給消費(fèi)者。這件事情本身就非常非常低效。很多文章都討論過(guò)Kafka速度快的原因,其中就談到了零拷貝技術(shù)——即數(shù)據(jù)不需要在頁(yè)緩存和堆緩存中來(lái)回拷貝。
簡(jiǎn)單來(lái)說(shuō)producer把生產(chǎn)的消息放到頁(yè)緩存上,如果兩邊版本一致,可以直接把此消息推給Consumer,或者Consumer直接拉取,這個(gè)過(guò)程是不需要把消息再放到堆緩存。但是你要做向下轉(zhuǎn)化或者版本不一致的話,就要額外把數(shù)據(jù)再堆上,然后再放回到Consumer上,速度特別慢。
1.Kafka調(diào)優(yōu) – 吞吐量
調(diào)優(yōu)吞吐量就是我們想用更短的時(shí)間做更多的事情。這里列出了客戶端需要調(diào)整的參數(shù)。前面說(shuō)過(guò)了producer是把消息放在緩存區(qū),后端Sender線程從緩存區(qū)拿出來(lái)發(fā)到broker。這里面涉及到一個(gè)打包的過(guò)程,它是批處理的操作,不是一條一條發(fā)送的。因此這個(gè)包的大小就和TPS息息相關(guān)。通常情況下調(diào)大這個(gè)值都會(huì)讓TPS提升,但是也不會(huì)無(wú)限制的增加。不過(guò)調(diào)高此值的劣處在于消息延遲的增加。除了調(diào)整batch.size,設(shè)置壓縮也可以提升TPS,它能夠減少網(wǎng)絡(luò)傳輸IO。當(dāng)前Lz4的壓縮效果是最好的,如果客戶端機(jī)器CPU資源很充足那么建議開啟壓縮。
對(duì)于消費(fèi)者端而言,調(diào)優(yōu)TPS并沒(méi)有太好的辦法,能夠想到的就是調(diào)整fetch.min.bytes。適當(dāng)?shù)卦黾釉搮?shù)的值能夠提升consumer端的TPS。對(duì)于Broker端而言,通常的瓶頸在于副本拉取消息時(shí)間過(guò)長(zhǎng),因此可以適當(dāng)?shù)卦黾觧um.replica.fetcher值,利用多個(gè)線程同時(shí)拉取數(shù)據(jù),可以加快這一進(jìn)程。
2.Kafka調(diào)優(yōu) – 延時(shí)
所謂的延時(shí)就是指消息被處理的時(shí)間。某些情況下我們自然是希望越快越好。針對(duì)這方面的調(diào)優(yōu),consumer端能做的不多,簡(jiǎn)單保持fetch.min.bytes默認(rèn)值即可,這樣可以保證consumer能夠立即返回讀取到的數(shù)據(jù)。講到這里,可能有人會(huì)有這樣的疑問(wèn):TPS和延時(shí)不是一回事嗎?假設(shè)發(fā)一條消息延時(shí)是2ms,TPS自然就是500了,因?yàn)橐幻胫荒馨l(fā)500消息,其實(shí)這兩者關(guān)系并不是簡(jiǎn)單的。因?yàn)槲野l(fā)一條消息2毫秒,但是如果把消息緩存起來(lái)統(tǒng)一發(fā),TPS會(huì)提升很多。假設(shè)發(fā)一條消息依然是2ms,但是我先等8毫秒,在這8毫秒之內(nèi)可能能收集到一萬(wàn)條消息,然后我再發(fā)。相當(dāng)于你在10毫秒內(nèi)發(fā)了一萬(wàn)條消息,大家可以算一下TPS是多少。事實(shí)上,Kafka producer在設(shè)計(jì)上就是這樣的實(shí)現(xiàn)原理。
3.Kafka調(diào)優(yōu) –消息持久性
消息持久化本質(zhì)上就是消息不丟失。Kafka對(duì)消息不丟失的承諾是有條件的。以前碰到很多人說(shuō)我給Kafka發(fā)消息,發(fā)送失敗,消息丟失了,怎么辦?嚴(yán)格來(lái)說(shuō)Kafka不認(rèn)為這種情況屬于消息丟失,因?yàn)榇藭r(shí)消息沒(méi)有放到Kafka里面。Kafka只對(duì)已經(jīng)提交的消息做有條件的不丟失保障。
如果要調(diào)優(yōu)持久性,對(duì)于producer而言,首先要設(shè)置重試以防止因?yàn)榫W(wǎng)絡(luò)出現(xiàn)瞬時(shí)抖動(dòng)造成消息發(fā)送失敗。一旦開啟了重試,還需要防止亂序的問(wèn)題。比如說(shuō)我發(fā)送消息1與2,消息2發(fā)送成功,消息1發(fā)送失敗重試,這樣消息1就在消息2之后進(jìn)入Kafka,也就是造成亂序了。如果用戶不允許出現(xiàn)這樣的情況,那么還需要顯式地設(shè)置max.in.flight.requests.per.connection為1。
本頁(yè)P(yáng)PT列出的其他參數(shù)都是很常規(guī)的參數(shù),比如unclean.leader.election.enable參數(shù),最好還是將其設(shè)置成false,即不允許“臟”副本被選舉為leader。
4.Kafka調(diào)優(yōu) –可用性
最后是可用性,與剛才的持久性是相反的,我允許消息丟失,只要保證系統(tǒng)高可用性即可。因此我需要把consumer心跳超時(shí)設(shè)置為一個(gè)比較小的值,如果給定時(shí)間內(nèi)消費(fèi)者沒(méi)有處理完消息,該實(shí)例可能就被踢出消費(fèi)者組。我想要其他消費(fèi)者更快地知道這個(gè)決定,因此調(diào)小這個(gè)參數(shù)的值。
六、定位性能瓶頸
下面就是性能瓶頸,嚴(yán)格來(lái)說(shuō)這不是調(diào)優(yōu),這是解決性能問(wèn)題。對(duì)于生產(chǎn)者來(lái)說(shuō),如果要定位發(fā)送消息的瓶頸很慢,我們需要拆解發(fā)送過(guò)程中的各個(gè)步驟。就像這張圖表示的那樣,消息的發(fā)送共有6步。第一步就是生產(chǎn)者把消息放到Broker,第二、三步就是Broker把消息拿到之后,寫到本地磁盤上,第四步是follower broker從Leader拉取消息,第五步是創(chuàng)建response;第六步是發(fā)送回去,告訴我已經(jīng)處理完了。
這六步當(dāng)中你需要確定瓶頸在哪?怎么確定?——通過(guò)不同的JMX指標(biāo)。比如說(shuō)步驟1是慢的,可能你經(jīng)常碰到超時(shí),你如果在日志里面經(jīng)常碰到request timeout,就表示1是很慢的,此時(shí)要適當(dāng)增加超時(shí)的時(shí)間。如果2、3慢的情況下,則可能體現(xiàn)在磁盤IO非常高,導(dǎo)致往磁盤上寫數(shù)據(jù)非常慢。倘若是步驟4慢的話,查看名為remote-time的JMX指標(biāo),此時(shí)可以增加fetcher線程的數(shù)量。如果5慢的話,表現(xiàn)為response在隊(duì)列導(dǎo)致待的時(shí)間過(guò)長(zhǎng),這時(shí)可以增加網(wǎng)絡(luò)線程池的大小。6與1是一樣的,如果你發(fā)現(xiàn)1、6經(jīng)常出問(wèn)題的話,查一下你的網(wǎng)絡(luò)。所以,就這樣來(lái)分解整個(gè)的耗時(shí)。這是到底哪一步的瓶頸在哪,需要看看什么樣的指標(biāo),做怎樣的調(diào)優(yōu)。
七、Java Consumer的調(diào)優(yōu)
最后說(shuō)一下Consumer的調(diào)優(yōu)。目前消費(fèi)者有兩種使用方式,一種是同一個(gè)線程里面就直接處理,另一種是我采用多帶帶的線程,consumer線程只是做獲取消息,消息真正的處理邏輯放到多帶帶的線程池中做。這兩種方式有不同的使用場(chǎng)景:第一種方法實(shí)現(xiàn)較簡(jiǎn)單,因?yàn)槟愕南⑻幚磉壿嬛苯訉懺谝粋€(gè)線程里面就可以了,但是它的缺陷在于TPS可能不會(huì)很高,特別是當(dāng)你的客戶端的機(jī)器非常強(qiáng)的時(shí)候,你用單線程處理的時(shí)候是很慢的,因?yàn)槟銢](méi)有充分利用線程上的CPU資源。第二種方法的優(yōu)勢(shì)是能夠充分利用底層服務(wù)器的硬件資源,TPS可以做的很高,但是處理提交位移將會(huì)很難。
最后說(shuō)一下參數(shù),也是網(wǎng)上問(wèn)的最多的,這幾個(gè)參數(shù)到底是做什么的。第一個(gè)參數(shù),就是控制consumer單次處理消息的最大時(shí)間。比如說(shuō)設(shè)定的是600s,那么consumer給你10分鐘來(lái)處理。如果10分鐘內(nèi)consumer無(wú)法處理完成,那么coordinator就會(huì)認(rèn)為此consumer已死,從而開啟rebalance。
Coordinator是用來(lái)管理消費(fèi)者組的協(xié)調(diào)者,協(xié)調(diào)者如何在有效的時(shí)間內(nèi),把消費(fèi)者實(shí)例掛掉的消息傳遞給其他消費(fèi)者,就靠心跳請(qǐng)求,因此可以設(shè)置heartbeat.interval.ms為一個(gè)較小的值,比如5s。
八、Q & A
Q1:胡老師在前面提到低版本與高版本有一個(gè)端口的問(wèn)題,我想問(wèn)一下高版本的、低版本的會(huì)有這個(gè)問(wèn)題嗎?
A1:會(huì)有。
Q2:兩種模式,一個(gè)是Consumer怎么做到所有的partition,在里面做管理的。會(huì)有一個(gè)問(wèn)題,某個(gè)Consumer的消費(fèi)比較慢,因?yàn)樗械腜artition的消費(fèi)都是綁定在一個(gè)線程。一個(gè)消費(fèi)比較慢,一個(gè)消費(fèi)比較快,要等另一個(gè)。有沒(méi)有一種方案,消費(fèi)者比較慢的可以暫定,如果涉及到暫停的話,頻繁的暫定耗費(fèi)的時(shí)間,是不是會(huì)比較慢?
A2:一個(gè)線程處理所有的分區(qū)。如果從開銷來(lái)講并不大,但是的確會(huì)出現(xiàn)像你說(shuō)的,如果一個(gè)消費(fèi)者定了100個(gè)分區(qū),目前我這邊看到的效果,某段時(shí)間內(nèi)有可能會(huì)造成某些分區(qū)的餓死,比如說(shuō)某些分區(qū)長(zhǎng)期得不到數(shù)據(jù),可能有一些分區(qū)不停的有數(shù)據(jù),這種情況下的確有可能情況。但是你說(shuō)的兩種方法本身開銷不是很大,因?yàn)樗褪莾?nèi)存當(dāng)中的結(jié)構(gòu)變更,就是定位信息,如果segment,就把定位信息先暫時(shí)關(guān)掉,不涉及到很復(fù)雜的數(shù)據(jù)結(jié)構(gòu)的變更。
Q3:怎么決定順序呢?
A3:這個(gè)事情現(xiàn)在在Broker端做的,簡(jiǎn)單會(huì)做輪詢,比如說(shuō)有100個(gè)分區(qū),第一批隨機(jī)給你一批分區(qū),之后這些分區(qū)會(huì)排到整個(gè)隊(duì)列的末尾,從其他的分區(qū)開始給你,做到盡量的公平。
Q4:消費(fèi)的時(shí)候會(huì)出現(xiàn)數(shù)據(jù)傾斜的情況,這塊如何理解?
A4:數(shù)據(jù)傾斜。這種情況下發(fā)生在每個(gè)消費(fèi)者訂閱信息不一樣的情況下,特別容易出現(xiàn)數(shù)據(jù)傾斜。比如說(shuō)我訂閱主題123,我訂閱主題456,我們又在同一個(gè)組里面這些主題分區(qū)數(shù)極不相同,很有可能出現(xiàn)我訂閱了10個(gè)分區(qū),你可能訂閱2個(gè)分區(qū)。如果你用的是有粘性的分配策略,那種保證不會(huì)出現(xiàn)超過(guò)兩個(gè)以上相差的情況。這個(gè)策略推出的時(shí)間也不算短了,是0.11版本推出來(lái)的。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/35948.html
摘要:作者胡夕人人貸計(jì)算平臺(tái)部總監(jiān),將在這篇專欄中一步一步的教你填平這些坑,全面提升你的實(shí)戰(zhàn)能力搭配掘金小冊(cè)圖解之核心原理學(xué)習(xí)效果更佳哦送學(xué)習(xí)筆記 showImg(https://segmentfault.com/img/bVbsg9O?w=258&h=258);關(guān)注有課學(xué)微信公眾號(hào),回復(fù)暗號(hào) kafka 獲取購(gòu)買《Kafka核心技術(shù)與實(shí)戰(zhàn)》極客時(shí)間專欄地址,購(gòu)買成功后提交購(gòu)買截圖即可獲得返...
摘要:在全面兼容Apache Kafka生態(tài)的基礎(chǔ)上,消息隊(duì)列Kafka徹底解決ApacheKafka穩(wěn)定性不足的長(zhǎng)期痛點(diǎn),并且支持消息無(wú)縫遷移到云上。 近日,阿里云宣布正式推出消息隊(duì)列Kafka,全面融合開源生態(tài)。在全面兼容Apache Kafka生態(tài)的基礎(chǔ)上,消息隊(duì)列Kafka還具備了超易用,超高可用可靠性,擴(kuò)縮容不操心,全方位安全診斷,數(shù)據(jù)安全有保障的特點(diǎn)。可用行達(dá)99.9%,數(shù)據(jù)可靠行99...
閱讀 3061·2023-04-26 02:27
閱讀 2773·2021-11-22 13:54
閱讀 910·2021-11-12 10:36
閱讀 3765·2021-10-09 09:44
閱讀 3187·2021-10-09 09:41
閱讀 1235·2021-09-22 10:02
閱讀 2845·2019-08-30 15:56
閱讀 3112·2019-08-30 11:02