Kafka是什么陈惰?
Kafka是一個(gè)分布式畦徘,有分區(qū)的毕籽,有副本的日志服務(wù)系統(tǒng),由LinkedIn公司開(kāi)發(fā)井辆,并于2011年開(kāi)源关筒。從本質(zhì)上來(lái)說(shuō),Kafka擁有一套可擴(kuò)展的發(fā)布/訂閱消息隊(duì)列架構(gòu)杯缺,并組成了一套分布式的日志系統(tǒng)蒸播,這套系統(tǒng)的創(chuàng)建,是為任何一家大公司搭建一套可處理實(shí)時(shí)數(shù)據(jù)的統(tǒng)一平臺(tái)萍肆。
和許多其他消息隊(duì)列系統(tǒng)相比(RabbitMQ袍榆,ActiveMQ,Redis)塘揣,Kafka有一些主要的區(qū)別:
- 如上面提到的包雀,Kafka底層是一個(gè)多副本的日志系統(tǒng)
- Kafka并不使用AMQP或其他已經(jīng)存在的通信協(xié)議,而是使用他自己特有的基于TCP的二進(jìn)制格式的協(xié)議
- Kafka很快亲铡,即便只使用很小的集群
- Kafka有強(qiáng)大的機(jī)制保證消息語(yǔ)義的順序和持久化
不考慮1.0之前的版本(當(dāng)前版本是0.9.0.1)才写,kafka已經(jīng)是產(chǎn)品化了,且被大量著名的企業(yè)在使用奖蔓,包括LinkedIn, Yahoo, Netflix, 和Datadog赞草。
整體架構(gòu)
在深入kafka之前,我們有必要了解一下kafka的整體架構(gòu)吆鹤,每一個(gè)版本都有以下這些組件組成厨疙,如圖所示:
生產(chǎn)者(producer)把消息發(fā)布到topic上,然后消費(fèi)者(consumer)把消息再?gòu)膖opic上消費(fèi)出來(lái)疑务,生產(chǎn)者和消費(fèi)者采取了一種推/拉(push/pull)的模式沾凄,生產(chǎn)者講消息推到topic上,而消費(fèi)者把消息從topic上拉下來(lái)暑始。Broker作為kafka集群的節(jié)點(diǎn)搭独,扮演著一個(gè)中間協(xié)調(diào)者的角色,它存儲(chǔ)著生產(chǎn)者發(fā)布上去的消息廊镜,并讓消費(fèi)者按照自己的速率來(lái)拉取牙肝。這意味著,broker是無(wú)狀態(tài)的嗤朴,他們不用跟蹤消費(fèi)的狀態(tài)配椭,然后會(huì)根據(jù)配置的保留策略(retention policy)來(lái)刪除消息。
消息本身是由最原始的二進(jìn)制字節(jié)數(shù)組(bytes)組成的雹姊,包含了topic和partition的信息股缸。kafka將消息以topic為單位區(qū)分,消費(fèi)者只訂閱他們需要的topic吱雏。kafka中的消息是按照時(shí)間戳排序且不可變敦姻,對(duì)消費(fèi)者而言瘾境,只有讀這一種操作。
topic被切分成多個(gè)分組(paritition)镰惦,而partition又被分配到多個(gè)broker上面迷守,這樣,topic就可以按照broker進(jìn)行數(shù)據(jù)分片旺入。如果分區(qū)數(shù)越大兑凿,那對(duì)于同一個(gè)topic而言,就可以同時(shí)支持多個(gè)消費(fèi)者的消費(fèi)茵瘾。
當(dāng)?shù)谝淮卧O(shè)置kafka的時(shí)候礼华,需要同時(shí)關(guān)注兩點(diǎn):給每一個(gè)topic分配足夠的parition和將parition平均第分配到各個(gè)broker上。如果在第一次部署kafka的時(shí)候就這樣做拗秘,可以減輕由于數(shù)據(jù)量增長(zhǎng)帶來(lái)的痛苦圣絮。如果想了解更多關(guān)于設(shè)置合理的topic數(shù)和parition數(shù),可以閱讀kafka作者Jun Rao的這篇優(yōu)秀的文章雕旨。
Kafka具有副本的功能晨雳,不同的broker上保存了每個(gè)parition的不同副本,具體存在幾臺(tái)broker上奸腺,是由配置的副本因子所決定的。盡管有大量副本的存在血久,但kafka只會(huì)在最初把數(shù)據(jù)寫(xiě)入partition的leader(一個(gè)leader多個(gè)follower)突照,leader是隨機(jī)的在ISR(in-sync replicas)池(所有處于同步狀態(tài)的partition副本)中選舉出來(lái)的。另外氧吐,消費(fèi)者只會(huì)讀取partition leader讹蘑,這樣follower副本將作為備份存在,以保證kafka的高可用性筑舅,從而防某個(gè)broker掛掉座慰。
還有很重要的一點(diǎn),沒(méi)有任何一個(gè)kafka版本是完全脫離zookeeper的翠拣,zookeeper就像膠水一樣把kafka的所有組件粘連在一起版仔,他的職責(zé)是:
- 選舉controller(其中某一臺(tái)kafka broker,用來(lái)管理所有的partition leader)
- 記錄集群的成員
- topic配置信息
- 磁盤(pán)分配(0.9+)
- 安全認(rèn)證管理 (0.9+)
- 消費(fèi)組成員管理(從0.9+以后刪除)
主要度量指標(biāo)
一個(gè)功能健全的kafka集群可以處理相當(dāng)大的數(shù)據(jù)量误墓,由于消息系統(tǒng)是很多大型應(yīng)用的基石蛮粮,因此broker集群在性能上的缺陷,都會(huì)引起整個(gè)應(yīng)用棧的各種問(wèn)題谜慌。
kafka的度量指標(biāo)主要有以下三類(lèi):
- kafka服務(wù)器(broker)指標(biāo)
- 生產(chǎn)者指標(biāo)
- 消費(fèi)者指標(biāo)
另外然想,由于kafka的狀態(tài)靠zookeeper來(lái)維護(hù),對(duì)于zookeeper性能的監(jiān)控也成為了整個(gè)kafka監(jiān)控計(jì)劃中一個(gè)必不可少的組成部分欣范。了解更多請(qǐng)看后續(xù)的系列文章变泄。
下面分別介紹上面提到的這三個(gè)方面的度量指標(biāo)令哟。
Broker度量指標(biāo)
kafka的服務(wù)端度量指標(biāo)是為了監(jiān)控broker,也是整個(gè)消息系統(tǒng)的核心妨蛹。因?yàn)樗邢⒍纪ㄟ^(guò)kafka broker傳遞屏富,然后被消費(fèi),所以對(duì)于broker集群上出現(xiàn)的問(wèn)題的監(jiān)控和告警就尤為重要滑燃。broker性能指標(biāo)有以下三類(lèi)
- kafka本身的指標(biāo)
- 主機(jī)層面的指標(biāo)
- JVM垃圾回收指標(biāo)
kafka本身的指標(biāo)
Name | MBean Name | Description | Metric Type |
---|---|---|---|
UnderReplicatedPartitions | kafka.server:type=ReplicaManager, name=UnderReplicatedPartitions | Number of unreplicated partitions | Resource: Availability |
IsrShrinksPerSec IsrExpandsPerSec | kafka.server:type=ReplicaManager, name=IsrShrinksPerSec kafka.server:type=ReplicaManager,name=IsrExpandsPerSec | Rate at which the pool of in-sync replicas (ISRs) shrinks/expands | Resource: Availability |
ActiveControllerCount | kafka.controller:type=KafkaController, name=ActiveControllerCount | Number of active controllers in cluster | Resource: Error |
OfflinePartitionsCount | kafka.controller:type=KafkaController, name=OfflinePartitionsCount | Number of offline partitions | Resource: Availability |
LeaderElectionRateAndTimeMs | kafka.controller:type=ControllerStats, name=LeaderElectionRateAndTimeMs | Leader election rate and latency | Other |
UncleanLeaderElectionsPerSec | kafka.controller:type=ControllerStats, name=UncleanLeaderElectionsPerSec | Number of "unclean" elections per second | Resource: Error |
TotalTimeMs | kafka.network:type=RequestMetrics,name=TotalTimeMs,request={Produce-FetchConsumer-FetchFollower} | Total time (in ms) to serve the specified request (Produce/Fetch) | Work: Performance |
PurgatorySize | kafka.server:type=ProducerRequestPurgatory,name=PurgatorySize kafka.server:type=FetchRequestPurgatory,name=PurgatorySize | Number of requests waiting in producer purgatory ; Number of requests waiting in fetch purgatory | Other |
BytesInPerSec BytesOutPerSec | kafka.server:type=BrokerTopicMetrics,name=BytesInPerSec kafka.server:type=BrokerTopicMetrics,name=BytesOutPerSec | Aggregate incoming/outgoing byte rate | Work: Throughput |
UnderReplicatedPartitions: 在一個(gè)運(yùn)行健康的集群中役听,處于同步狀態(tài)的副本數(shù)(ISR)應(yīng)該與總副本數(shù)(簡(jiǎn)稱(chēng)AR:Assigned Repllicas)完全相等,如果分區(qū)的副本遠(yuǎn)遠(yuǎn)落后于leader表窘,那這個(gè)follower將被ISR池刪除典予,隨之而來(lái)的是IsrShrinksPerSec(可理解為isr的縮水情況,后面會(huì)講)的增加乐严。由于kafka的高可用性必須通過(guò)副本來(lái)滿(mǎn)足瘤袖,所有有必要重點(diǎn)關(guān)注這個(gè)指標(biāo),讓它長(zhǎng)期處于大于0的狀態(tài)昂验。
IsrShrinksPerSec/IsrExpandsPerSec: 任意一個(gè)分區(qū)的處于同步狀態(tài)的副本數(shù)(ISR)應(yīng)該保持穩(wěn)定捂敌,只有一種例外,就是當(dāng)你擴(kuò)展broker節(jié)點(diǎn)或者刪除某個(gè)partition的時(shí)候既琴。為了保證高可用性占婉,健康的kafka集群必須要保證最小ISR數(shù),以防在某個(gè)partiton的leader掛掉時(shí)它的follower可以接管甫恩。一個(gè)副本從ISR池中移走有以下一些原因:follower的offset遠(yuǎn)遠(yuǎn)落后于leader(改變replica.lag.max.messages
配置項(xiàng))逆济,或者某個(gè)follower已經(jīng)與leader失去聯(lián)系了某一段時(shí)間(改變replica.socket.timeout.ms
配置項(xiàng)),不管是什么原因磺箕,如果IsrShrinksPerSec(ISR縮水) 增加了奖慌,但并沒(méi)有隨之而來(lái)的IsrExpandsPerSec(ISR擴(kuò)展)的增加,就將引起重視并人工介入松靡,kafka官方文檔提供了大量關(guān)于broker的用戶(hù)可配置參數(shù)简僧。
ActiveControllerCount: kafka集群中第一個(gè)啟動(dòng)的節(jié)點(diǎn)自動(dòng)成為了controller,有且只能有一個(gè)這樣的節(jié)點(diǎn)雕欺。controller的職責(zé)是維護(hù)partitio leader的列表岛马,和協(xié)調(diào)leader的變更(當(dāng)遇到某個(gè)partiton leader不可用時(shí))。如果有必要更換controller阅茶,一個(gè)新的controller將會(huì)被zookeeper從broker池中隨機(jī)的選取出來(lái)蛛枚,通常來(lái)說(shuō),這個(gè)值(ActiveControllerCount)不可能大于1脸哀,但是當(dāng)遇到這個(gè)值等于0且持續(xù)了一小段時(shí)間(<1秒)的時(shí)候蹦浦,必須發(fā)出明確的告警。
OfflinePartitionsCount (只有controller有): 這個(gè)指標(biāo)報(bào)告了沒(méi)有活躍leader的partition數(shù)撞蜂,由于所有的讀寫(xiě)操作都只在partition leader上進(jìn)行盲镶,因此非0的這個(gè)值需要被告警出來(lái)侥袜,從而防止服務(wù)中斷。任何沒(méi)有活躍leader的partition都會(huì)徹底不可用溉贿,且該parition上的消費(fèi)者和生產(chǎn)者都將被阻塞枫吧,直到leader變成可用。
LeaderElectionRateAndTimeMs: 當(dāng)parition leader掛了以后宇色,新leader的選舉就被觸發(fā)九杂。當(dāng)partition leader與zookeeper失去連接以后,它就被人為是“死了”宣蠕,不像zookeeper zab例隆,kafka沒(méi)有專(zhuān)門(mén)對(duì)leader選舉采用majority-consensus算法。是kafka的broker集群所有的機(jī)器列表抢蚀,是由每一個(gè)parition的ISR所包含的機(jī)器這個(gè)子集镀层,加起來(lái)的并集組成的,怎么說(shuō)皿曲,假設(shè)一共有3個(gè)parition唱逢,第一個(gè)parition的ISR包含broker1、2屋休、3坞古,第二個(gè)parition包含broker2、3劫樟、4绸贡,第三個(gè)parition包含broker3、4毅哗、5,那么這三個(gè)parition的ISR所在broker節(jié)點(diǎn)加起來(lái)的并集就是整個(gè)kafka集群的所有broker全集1捧挺、2虑绵、3、4闽烙、5翅睛。當(dāng)副本可以被leader捕獲到的時(shí)候,我們就人為它處于同步狀態(tài)(in-sync)黑竞,這意味著任何在ISR池中的節(jié)點(diǎn)捕发,都有可能被選舉為leader。
LeaderElectionRateAndTimeMs 報(bào)告了兩點(diǎn):leader選舉的頻率(每秒鐘多少次)和集群中無(wú)leader狀態(tài)的時(shí)長(zhǎng)(以毫秒為單位)很魂,盡管不像UncleanLeaderElectionsPerSec這個(gè)指標(biāo)那么嚴(yán)重扎酷,但你也需要時(shí)長(zhǎng)關(guān)注它,就像上文提到的遏匆,leader選舉是在與當(dāng)前l(fā)eader通信失敗時(shí)才會(huì)觸發(fā)的法挨,所以這種情況可以理解為存在一個(gè)掛掉的broker谁榜。
UncleanLeaderElectionsPerSec: 這個(gè)指標(biāo)如果存在的話很糟糕,這說(shuō)明kafka集群在尋找partition leader節(jié)點(diǎn)上出現(xiàn)了故障凡纳,通常窃植,如果某個(gè)作為partition leader的broker掛了以后,一個(gè)新的leader會(huì)被從ISR集合中選舉出來(lái)荐糜,不干凈的leader選舉(Unclean leader elections )是一種特殊的情況巷怜,這種情況是副本池中沒(méi)有存活的副本”┦希基于每個(gè)topic必須擁有一個(gè)leader延塑,而如果首領(lǐng)是從處于不同步狀態(tài)的副本中選舉出來(lái)的話,意味著那些與之前的leader沒(méi)有被同步的消息偏序,將會(huì)永久性丟失页畦。事實(shí)上,不干凈的leader選舉將犧牲持久性(consistency)來(lái)保證可用性(availability)研儒。所以豫缨,我們必須明確地得到這個(gè)指標(biāo)的告警,從而告知數(shù)據(jù)的丟失端朵。
TotalTimeMs: The TotalTimeMs metric family measures the total time taken to service a request (be it a produce, fetch-consumer, or fetch-follower request):
這個(gè)指標(biāo)族(很多地方都涉及到它)衡量了各種服務(wù)請(qǐng)求的時(shí)間(包括produce好芭,fetch-consumer,fetch-follower)
produce:從producer發(fā)起請(qǐng)求發(fā)送數(shù)據(jù)
fetch-consumer: 從consumer發(fā)起請(qǐng)求獲取數(shù)據(jù)
fetch-follower:follower節(jié)點(diǎn)向leader節(jié)點(diǎn)發(fā)起請(qǐng)求冲呢,同步數(shù)據(jù)
TotalTimeMs 這個(gè)指標(biāo)是由4個(gè)其他指標(biāo)的總和構(gòu)成的:
queue:處于請(qǐng)求隊(duì)列中的等待時(shí)間
local:leader節(jié)點(diǎn)處理的時(shí)間
remote:等待follower節(jié)點(diǎn)響應(yīng)的時(shí)間(只有當(dāng)
requests.required.acks=-1時(shí)
)response:發(fā)送響應(yīng)的時(shí)間
通常情況下舍败,這個(gè)指標(biāo)值是比較穩(wěn)定的,只有很小的波動(dòng)敬拓。當(dāng)你看到不規(guī)則的數(shù)據(jù)波動(dòng)邻薯,你必須檢查每一個(gè)queue,local,remote和response的值,從而定位處造成延遲的原因到底處于哪個(gè)segment乘凸。
PurgatorySize: 請(qǐng)求煉獄(request purgatory)作為一個(gè)臨時(shí)存放的區(qū)域厕诡,使得生產(chǎn)(produce)和消費(fèi)(fetch)的請(qǐng)求在那里等待直到被需要的時(shí)候。每個(gè)類(lèi)型的請(qǐng)求都有各自的參數(shù)配置营勤,從而決定是否(將消息)添加到煉獄中:
fetch:當(dāng)
fetch.wait.max.ms
定義的時(shí)間已到灵嫌,還沒(méi)有足夠的數(shù)據(jù)來(lái)填充(congsumer的fetch.min.bytes
)請(qǐng)求的時(shí)候,獲取消息的請(qǐng)求就會(huì)被扔到煉獄中葛作。produce:當(dāng)
request.required.acks=-1寿羞,所有的生產(chǎn)請(qǐng)求都會(huì)被暫時(shí)放到煉獄中,直到partition leader收到follower的確認(rèn)消息赂蠢。
關(guān)注煉獄的大小有助于判斷導(dǎo)致延遲的原因是什么绪穆,比如說(shuō),導(dǎo)致fetch時(shí)間的增加,很顯然可以認(rèn)為是由于煉獄中fetch的請(qǐng)求增加了霞幅。
BytesInPerSec/BytesOutPerSec: 通常漠吻,磁盤(pán)的吞吐量往往是決定kafka性能的瓶頸,但也不是說(shuō)網(wǎng)絡(luò)就不會(huì)成為瓶頸司恳。根據(jù)你實(shí)際的使用場(chǎng)景途乃,硬件和配置,網(wǎng)絡(luò)將很快會(huì)成為消息傳輸過(guò)程中最慢的一個(gè)環(huán)節(jié)扔傅,尤其是當(dāng)你的消息跨數(shù)據(jù)中心傳輸?shù)臅r(shí)候耍共。跟蹤節(jié)點(diǎn)之間的網(wǎng)絡(luò)吞吐量,可以幫助你找到潛在的瓶頸在哪里猎塞,而且可以幫助決策是否需要把端到端的消息做壓縮處理试读。
主機(jī)層面的broker性能指標(biāo)
Name | Description | Metric Type |
---|---|---|
Page cache reads ratio | Ratio of reads from page cache vs reads from disk | Resource: Saturation |
Disk usage | Disk space currently consumed vs available | Resource: Utilization |
CPU usage | CPU use | Resource: Utilization |
Network bytes sent/received | Network traffic in/out | Resource: Utilization |
Page cache read ratio: kafka在設(shè)計(jì)最初的時(shí)候,通過(guò)內(nèi)核中的頁(yè)緩存荠耽,來(lái)達(dá)到溝通可靠性(基于磁盤(pán))和高效性(基于內(nèi)存)之間的橋梁钩骇。page cache read ratio(可理解為頁(yè)緩存讀取率),和數(shù)據(jù)庫(kù)中的cache-hit ratio(緩存命中率)比較相似铝量,如果這個(gè)值比較大倘屹,則等價(jià)于更快的讀取速度,從而有更好的性能慢叨。如果發(fā)現(xiàn)頁(yè)緩存讀取率<80%纽匙,則說(shuō)明需要增加broker了。
Disk usage: 由于kafka將所有數(shù)據(jù)持久化到磁盤(pán)上拍谐,很有必要監(jiān)控一下kafka的剩余磁盤(pán)空間烛缔。當(dāng)磁盤(pán)占滿(mǎn)時(shí),kafka會(huì)失敗轩拨,所以践瓷,隨著時(shí)間的推移,跟蹤磁盤(pán)的增長(zhǎng)率是很有必要的亡蓉。一旦你了解了磁盤(pán)的增長(zhǎng)速率当窗,你就可以在磁盤(pán)將要占滿(mǎn)之前選擇一個(gè)合適的時(shí)間通知管理員。
CPU usage: 盡管kafka主要的瓶頸通常是內(nèi)存寸宵,但并不妨礙觀察一下cpu的使用率。雖然即便在使用gzip壓縮的場(chǎng)景下元咙,cpu都不太可能對(duì)性能產(chǎn)生影響梯影,但是,如果發(fā)現(xiàn)cpu使用率突然增高庶香,那肯定要引起重視了甲棍。
Network bytes sent/received: 如果你只是在監(jiān)控kafka的網(wǎng)絡(luò)in/out指標(biāo),那你只會(huì)了解到跟kafka相關(guān)的信息赶掖。如果要全面了解主機(jī)的網(wǎng)絡(luò)使用情況感猛,你必須監(jiān)控主機(jī)層面的網(wǎng)絡(luò)吞吐量七扰,尤其是當(dāng)你的kafka主機(jī)還承載了其他與網(wǎng)絡(luò)有關(guān)的服務(wù)。高網(wǎng)絡(luò)使用率是性能下降的一種表現(xiàn)陪白,此時(shí)需要聯(lián)系TCP重傳和丟包錯(cuò)誤颈走,來(lái)決定性能的問(wèn)題是否是網(wǎng)絡(luò)相關(guān)的。
JVM垃圾回收指標(biāo)
由于kafka是由scala編寫(xiě)的咱士,且運(yùn)行在java虛擬機(jī)上立由,需要依賴(lài)java的垃圾回收機(jī)制來(lái)釋放內(nèi)存,如果kafka集群越活躍序厉,則垃圾回收的頻率也就越高锐膜。
只要對(duì)java有些了解的人都應(yīng)該知道垃圾回收會(huì)產(chǎn)生很大的性能開(kāi)銷(xiāo),(垃圾回收造成的)暫停對(duì)kafka最大的影響就是會(huì)造成大量廢棄的zookeeper session(因?yàn)閟ession超時(shí)了)弛房。
垃圾回收的類(lèi)型是基于回收的是年輕代(新的對(duì)象)還是老年代(長(zhǎng)期存活的對(duì)象)道盏,初學(xué)者可以看這篇關(guān)于垃圾回收的文章:
當(dāng)發(fā)現(xiàn)垃圾回收造成了過(guò)度的暫停,你可以考慮升級(jí)JDK版本或者垃圾回收器(或者增加zookeeper.session.timeout.ms來(lái)防止time out
)文捶。另外荷逞,可以調(diào)節(jié)java runtime參數(shù)來(lái)最小化垃圾回收。LInkedin的工程師寫(xiě)了這么一篇深入介紹優(yōu)化垃圾回收的文章拄轻,供參考颅围。當(dāng)然,也可以直接參考kafka官方文檔中給出的推薦配置恨搓。
Name | MBean Name | Description | Type |
---|---|---|---|
ParNew count | java.lang:type=GarbageCollector,name=ParNew | Number of young-generation collections | Other |
ParNew time | java.lang:type=GarbageCollector,name=ParNew | Elapsed time of young-generation collections, in milliseconds | Other |
ConcurrentMarkSweep count | java.lang:type=GarbageCollector,name=ConcurrentMarkSweep | Number of old-generation collections | Other |
ConcurrentMarkSweep time | java.lang:type=GarbageCollector,name=ConcurrentMarkSweep | Elapsed time of old-generation collections, in milliseconds | Other |
ParNew:可以理解成年輕代院促,這部分的垃圾回收會(huì)相當(dāng)頻繁,ParNew是一個(gè)stop-the-world的垃圾回收斧抱,意味著所有應(yīng)用線程都將被暫停常拓,知道垃圾回收完成,所以ParNew延遲的任何增加都會(huì)對(duì)kafka的性能造成嚴(yán)重影響辉浦。
ConcurrentMarkSweep (CMS) :這種垃圾回收清理了堆上的老年代不用的內(nèi)存弄抬,CMS是一個(gè)短暫暫停的垃圾回收算法,盡管會(huì)造成應(yīng)用線程的短暫停頓宪郊,但這只是間歇性的掂恕,如果CMS需要幾秒鐘才能完成,或者發(fā)生的頻次增加弛槐,那么集群就沒(méi)有足夠的內(nèi)存來(lái)滿(mǎn)足基本功能懊亡。
kafka生產(chǎn)者指標(biāo)
kafka的生產(chǎn)者是專(zhuān)門(mén)把消息推送到broker的topic上供別人消費(fèi)的,如果producer失敗了乎串,那consumer也將無(wú)法消費(fèi)到新的消息店枣,下面是生產(chǎn)者的幾個(gè)有用的重要監(jiān)控指標(biāo),保證數(shù)據(jù)流的穩(wěn)定性。
Name | v0.8.2.x MBean Name | v0.9.0.x MBean Name | Description | Metric Type |
---|---|---|---|---|
Response rate | N/A | kafka.producer:type=producer-metrics,client-id=([-.w]+) | Average number of responses received per second | Work: Throughput |
Request rate | kafka.producer:type=ProducerRequestMetrics, name=ProducerRequestRateAndTimeMs,clientId=([-.w]+) | kafka.producer:type=producer-metrics,client-id=([-.w]+) | Average number of requests sent per second | Work: Throughput |
Request latency avg | kafka.producer:type=ProducerRequestMetrics, name=ProducerRequestRateAndTimeMs,clientId=([-.w]+) | kafka.producer:type=producer-metrics,client-id=([-.w]+) | Average request latency (in ms) | Work: Throughput |
Outgoing byte rate | kafka.producer:type=ProducerTopicMetrics, name=BytesPerSec,clientId=([-.w]+) | kafka.producer:type=producer-metrics,client-id=([-.w]+) | Average number of outgoing/incoming bytes per second | Work: Throughput |
IO wait time ns avg | N/A | kafka.producer:type=producer-metrics,client-id=([-.w]+) | Average length of time the I/O thread spent waiting for a socket (in ns) | Work: Throughput |
對(duì)生產(chǎn)者來(lái)說(shuō)鸯两,響應(yīng)速率表示從broker上得到響應(yīng)的速率闷旧,當(dāng)broker接收到producer的數(shù)據(jù)時(shí)會(huì)給出響應(yīng),根據(jù)配置钧唐,“接收到”包含三層意思:
- 消息已接收到忙灼,但并未確認(rèn)(
request.required.acks == 0
) - leader已經(jīng)把數(shù)據(jù)寫(xiě)入磁盤(pán)(
request.required.acks == 1
) - leader節(jié)點(diǎn)已經(jīng)從其他follower節(jié)點(diǎn)上接收到了數(shù)據(jù)已寫(xiě)入磁盤(pán)的確認(rèn)消息(
request.required.acks == -1
)
這看上去很完美,但是對(duì)消費(fèi)者而言逾柿,只有當(dāng)上述的這些確認(rèn)步驟都準(zhǔn)確無(wú)誤以后缀棍,才能讀取到producer生產(chǎn)的數(shù)據(jù)。
如果你發(fā)現(xiàn)響應(yīng)速率很低机错,那是因?yàn)樵谶@個(gè)過(guò)程中需要牽扯太多因素爬范,一個(gè)很簡(jiǎn)單的辦法就是檢查broker上配置的request.required.acks參數(shù),根據(jù)你的使用場(chǎng)景來(lái)選擇合適的值弱匪,到底是更看中可用性(availability)還是持久性(consistency)青瀑,前者強(qiáng)調(diào)消費(fèi)者是否能盡快讀取到可用的消息,而后者強(qiáng)調(diào)消息是否準(zhǔn)確無(wú)誤地持久化寫(xiě)入某個(gè)topic的某個(gè)partition的所有副本的磁盤(pán)中萧诫。
Request rate:請(qǐng)求的速率是指數(shù)據(jù)從producer發(fā)送到broker的速率斥难,很顯然,請(qǐng)求的速率變化是否健康帘饶,也是由使用的場(chǎng)景所決定的哑诊。關(guān)注速率走勢(shì)的上和下,對(duì)于保證服務(wù)的可用性非常關(guān)鍵及刻,如果不開(kāi)啟速率限制(rate-limiting)(0.9+版本才有)镀裤,那么當(dāng)流量高峰來(lái)臨時(shí),broker就將變得很慢缴饭,因?yàn)樗τ谔幚泶罅坑咳氲臄?shù)據(jù)暑劝。
Request latency average: 平均請(qǐng)求延遲,這是用來(lái)衡量從producer調(diào)用KafkaProducer.send()方法到接收到broker響應(yīng)的時(shí)長(zhǎng)颗搂〉C停“接收到”包含很多層意思,可參考
response rate那一塊丢氢。
有多種途徑可以減少延遲傅联,主要的途徑是producer的linger.ms
配置項(xiàng),這個(gè)配置項(xiàng)告訴producer疚察,在累積夠一個(gè)消息批次之前蒸走,需要等待多久才能發(fā)送。默認(rèn)地稍浆,producer只要接收到上一次發(fā)送的確認(rèn)消息后,就立即發(fā)送新的消息,但并非所有場(chǎng)景都適用衅枫,為了累積消息而等待一點(diǎn)時(shí)間會(huì)提高吞吐量嫁艇。
由于延遲和吞吐量有著必然的聯(lián)系,就很有必要關(guān)注batch.size這個(gè)producer配置項(xiàng)弦撩,從而達(dá)到更完美的吞吐量步咪。并不是只要配置一個(gè)合適的值就可以一勞永逸了,要視情況決定如何選擇一個(gè)更優(yōu)的批大小益楼。要記住猾漫,你所配置的批大小是一個(gè)上限值,意思是說(shuō)感凤,如果數(shù)據(jù)滿(mǎn)了悯周,就立即發(fā)送,但如果沒(méi)滿(mǎn)的話陪竿,最多只等linger.ms
毫秒禽翼,小的批量將會(huì)導(dǎo)致更多次數(shù)的網(wǎng)絡(luò)通信,然后降低吞吐量族跛,反之亦然闰挡。
Outgoing byte rate: 在kafka的broker中翰铡,肯定需要監(jiān)控producer的網(wǎng)絡(luò)吞吐量狱庇,隨著時(shí)間的變化觀察網(wǎng)絡(luò)上的數(shù)據(jù)傳輸量是很有必要的杠巡,從而決定是否有必要調(diào)整網(wǎng)絡(luò)設(shè)備答捕。另外笙蒙,也很有必要知道producer是否以一個(gè)恒定的速率發(fā)送數(shù)據(jù)沉填,從而讓consumer獲取到有鹿。監(jiān)控producer的網(wǎng)絡(luò)傳輸情況尚困,除了可以決定是否需要調(diào)整網(wǎng)絡(luò)設(shè)備掏膏,也可以了解producer的生產(chǎn)效率劳翰,以及定位傳輸延遲的原因。
IO wait time: Producer通常做了這么一些事:等待數(shù)據(jù)和發(fā)送數(shù)據(jù)馒疹。當(dāng)producer產(chǎn)生了超越他發(fā)送能力的數(shù)據(jù)量佳簸,那結(jié)果就是只能等待網(wǎng)絡(luò)資源。當(dāng)如果producer沒(méi)有發(fā)送速度限制颖变,或者盡可能增加帶寬生均,就很難說(shuō)這(網(wǎng)絡(luò)延遲)是個(gè)瓶頸了。因?yàn)榇疟P(pán)的讀寫(xiě)速率往往是最耗時(shí)的一個(gè)環(huán)節(jié)腥刹,所以對(duì)producer而言马胧,最好檢查一下I/O等待的時(shí)間。請(qǐng)記住衔峰,I/O等待表示當(dāng)CPU停下來(lái)等待I/O的時(shí)間佩脊,如果你發(fā)現(xiàn)了過(guò)分的等待時(shí)間蛙粘,這說(shuō)明producer無(wú)法足夠快地獲取他需要的數(shù)據(jù),如果你還在使用傳統(tǒng)的機(jī)械磁盤(pán)作為存儲(chǔ)威彰,那請(qǐng)考慮采用SSD出牧。
Kafka消費(fèi)者指標(biāo)
0.8.2.2版本
在0.8.2.2版本中,消費(fèi)者指標(biāo)分成兩類(lèi):簡(jiǎn)單消費(fèi)者指標(biāo)和高階消費(fèi)者指標(biāo)歇盼。
所有簡(jiǎn)單消費(fèi)者指標(biāo)都被高階消費(fèi)者采納舔痕,但反過(guò)來(lái)并非如此。這兩者之間最主要的區(qū)別就是開(kāi)發(fā)者對(duì)于消費(fèi)者的掌控程度不同豹缀。
簡(jiǎn)單消費(fèi)者伯复,事實(shí)上就是那些被明確地告知連接哪個(gè)broker,哪個(gè)partition邢笙。簡(jiǎn)單消費(fèi)者也可以自行管理offset和進(jìn)行parition leader的選舉啸如。盡管為了保證消費(fèi)者可以真正運(yùn)行起來(lái),需要做很多工作鸣剪,但簡(jiǎn)單消費(fèi)者也是相對(duì)更靈活的组底。
高階消費(fèi)者(也被稱(chēng)為消費(fèi)者組)忽略了大量實(shí)施過(guò)程中的細(xì)節(jié),那些細(xì)節(jié)包括offset的位置筐骇,broker leader债鸡,和zookeeper管理的分區(qū)可用性,消費(fèi)者組只做他最擅長(zhǎng)的事铛纬,就是消費(fèi)數(shù)據(jù)厌均。然而,其實(shí)簡(jiǎn)單消費(fèi)者更強(qiáng)大告唆,高階消費(fèi)者更靈活棺弊。
0.9.0.0+版本
kafka0.9.0.0版本包括了很多新特性,包括了對(duì)consumer api的很多大調(diào)整擒悬。在0.9+以上版本中模她,專(zhuān)門(mén)定義了一類(lèi)消費(fèi)者指標(biāo),可以通過(guò)調(diào)用新api得到懂牧,這些消費(fèi)者指標(biāo)把0.8.2.2中的普通消費(fèi)者和高階消費(fèi)者結(jié)合到了一起侈净,而且使用了完全不同的MBean命名空間。
Name | v0.8.2.x MBean Name | v0.9.0.x MBean Name | Description | Metric Type | v0.8.2.x Consumer Type |
---|---|---|---|---|---|
ConsumerLag MaxLag | broker offset - consumer offset kafka.consumer:type= ConsumerFetcherManager, name=MaxLag, clientId=([-.\w]+) | broker offset - consumer offset Attribute: records-lag-max, kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.w]+) | Number of messages consumer is behind producer / Maximum number of messages consumer is behind producer | Work: Performance | Simple Consumer |
BytesPerSec | kafka.consumer:type= ConsumerTopicMetrics, name=BytesPerSec, clientId=([-.\w]+) | kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.\w]+) | Bytes consumed per second | Work: Throughput | Simple Consumer |
MessagesPerSec | kafka.consumer:type= ConsumerTopicMetrics, name=MessagesPerSec, clientId=([-.\w]+) | kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.\w]+) | Messages consumed per second | Work: Throughput | Simple Consumer |
ZooKeeperCommitsPerSec | kafka.consumer:type= ZookeeperConsumerConnector, name=ZooKeeperCommitsPerSec, clientId=([-.\w]+) | N/A | Rate of consumer offset commits to ZooKeeper | Work: Throughput | High-level Consumer |
MinFetchRate | kafka.consumer:type= ConsumerFetcherManager, name=MinFetchRate, clientId=([-.\w]+) | Attribute: fetch-rate, kafka.consumer:type=consumer-fetch-manager-metrics,client-id=([-.w]+) | Minimum rate a consumer fetches requests to the broker | Work: Throughput |
ConsumerLag/MaxLag:這是所有人都很中意的kafka指標(biāo)僧凤,ConsumerLag是指consumer當(dāng)前的日志偏移量相對(duì)生產(chǎn)者的日志偏移量畜侦,MaxLag和ConsumerLag的關(guān)系很緊密,相當(dāng)于是觀察到的ConsumerLag的最大值躯保,這兩個(gè)度量指標(biāo)的重要性在于旋膳,可以決定你的消費(fèi)者在做什么。如果采用一個(gè)消費(fèi)者組在存儲(chǔ)設(shè)備上存儲(chǔ)大量老的消息途事,你就需要重點(diǎn)關(guān)注消費(fèi)者的延遲验懊。當(dāng)然擅羞,如果你的消費(fèi)者處理的是實(shí)時(shí)消息,如果lag值一直居高不下义图,那就說(shuō)明消費(fèi)者有些過(guò)載(overloaded)了祟滴,遇到這種情況,就需要采用更多的消費(fèi)者歌溉,和把topic切分成多個(gè)parition,從而可以提高吞吐量和降低延遲骑晶。
注意:ConsumerLag 是kafka之中過(guò)載的表現(xiàn)痛垛,正如上面的定義中所描述的額一樣,但它也可被用來(lái)表示partition leader和follower之間的offset差異桶蛔。
BytesPerSec:正如前文提到的生產(chǎn)者和broker的關(guān)系匙头,也需要監(jiān)控消費(fèi)者的網(wǎng)絡(luò)吞吐量。比如仔雷,MessagesPerSec的突然下降可能會(huì)導(dǎo)致消費(fèi)失敗蹂析,但如果BytesPerSec還保持不變,那如果消費(fèi)少批次大體量的消息問(wèn)題還不大碟婆。不斷觀察網(wǎng)絡(luò)的流量电抚,就像其他度量指標(biāo)中提到的一樣,診斷不正常的網(wǎng)絡(luò)使用情況是很重要的竖共。
MessagesPerSec: 消息的消費(fèi)速度并不完全等同于比特的消費(fèi)速度蝙叛,因?yàn)橄⒈旧砜赡苡胁煌笮 R蕾?lài)生產(chǎn)者和工作負(fù)載量公给,在典型的部署環(huán)境中借帘,往往希望這個(gè)值是相當(dāng)穩(wěn)定的。通過(guò)隨著時(shí)間的推移監(jiān)控這個(gè)指標(biāo)淌铐,可以觀察出消費(fèi)數(shù)據(jù)的趨勢(shì),然后定出一個(gè)基線腿准,從而確定告警的閾值际起。這個(gè)曲線的走勢(shì)取決于你的使用場(chǎng)景,但不管怎樣释涛,在很多情況下加叁,定出一條基線然后對(duì)于異常情況做出告警是很有必要的。
ZooKeeperCommitsPerSec:只有0.8x版本有唇撬,如果把zookeeper作為offset的存儲(chǔ)(在0.8x版本中是默認(rèn)的它匕,0.9+版本必須顯式地在配置中定義offsets.storage=zookeeper
),那你肯定需要監(jiān)控這個(gè)值窖认。注意到如果想要在0.9+版本中明確使用zookeeper作為offset存儲(chǔ)豫柬,這個(gè)指標(biāo)并沒(méi)有被開(kāi)放告希。當(dāng)zookeeper處于高寫(xiě)負(fù)載的時(shí)候,將會(huì)遇到成為性能瓶頸烧给,從而導(dǎo)致從kafka管道抓取數(shù)據(jù)變得緩慢燕偶。隨著時(shí)間推移跟蹤這個(gè)指標(biāo),可以幫助定位到zookeeper的性能問(wèn)題础嫡,如果發(fā)現(xiàn)有大量發(fā)往zookeeper的commit請(qǐng)求指么,你需要考慮的是,要不對(duì)zookeeper集群進(jìn)行擴(kuò)展榴鼎,要不直接把offset的存儲(chǔ)變?yōu)閗afka(offsets.storage=kafka
)伯诬。記住,這個(gè)指標(biāo)只對(duì)高階消費(fèi)者有用巫财,簡(jiǎn)單消費(fèi)者自行管理offset盗似。
MinFetchRate: 消費(fèi)者拉取的速率很好反映了消費(fèi)者的整體健康狀況,如果最小拉取速率接近0的話平项,就可能說(shuō)明消費(fèi)者出現(xiàn)問(wèn)題了赫舒,對(duì)一個(gè)健康的消費(fèi)者來(lái)說(shuō),最小拉取速率通常都是非0的闽瓢,所以如果發(fā)現(xiàn)這個(gè)值在下降接癌,往往就是消費(fèi)者失敗的標(biāo)志。
為什么要用zookeeper扣讼?
zookeeper在kafka的集群中扮演了非常重要的角色扔涧,他的職責(zé)是:維護(hù)消費(fèi)者的offset和topic列表,leader選舉届谈,以及某些常用的狀態(tài)信息枯夜。在kafka0.8版本中,broker和consumer的協(xié)作都是通過(guò)zookeeper來(lái)進(jìn)行的艰山,在0.9版本中湖雹,zookeeper只是被broker用到(默認(rèn)是這樣的,除非你有其他配置)曙搬,這樣會(huì)大大地降低zookeeper的負(fù)載摔吏,尤其是在大集群中。
Zookeeper度量指標(biāo)
可以通過(guò)MBean和命令行接口來(lái)獲取zookeeper的度量指標(biāo)纵装,
Name | Description | Metric Type |
---|---|---|
zk_outstanding_requests |
Number of requests queued | Resource: Saturation |
zk_avg_latency |
Amount of time it takes to respond to a client request (in ms) | Work: Throughput |
zk_num_alive_connections |
Number of clients connected to ZooKeeper | Resource: Availability |
zk_followers |
Number of active followers | Resource: Availability |
zk_pending_syncs |
Number of pending syncs from followers | Other |
zk_open_file_descriptor_count |
Number of file descriptors in use | Resource: Utilization |
Bytes sent/received:在0.8x版本中征讲,broker和consumer都要和zookeeper通信,大規(guī)模部署的集群中橡娄,有很多consumer和partition诗箍,這種和zookeeper連續(xù)不斷地通信將會(huì)成為zookeeper的瓶頸,因?yàn)閦ookeeper是串行處理請(qǐng)求的挽唉。根據(jù)時(shí)間變化跟蹤發(fā)送和接受數(shù)據(jù)比特大小可以幫助診斷性能問(wèn)題滤祖。如果zookeeper集群需要連續(xù)不斷處理大流量筷狼,那么就需要為集群提供更多節(jié)點(diǎn),來(lái)適應(yīng)更大數(shù)據(jù)量匠童。
Usable memory: zookeeper需要加載大量數(shù)據(jù)到內(nèi)存中埂材,當(dāng)需要page到磁盤(pán)上的時(shí)候是最痛苦的。所以汤求,為了使zookeeper的性能更優(yōu)俏险,跟蹤內(nèi)存使用率是很有必要的。記住扬绪,因?yàn)閦ookeeper是用來(lái)保存狀態(tài)的寡喝,所以zookeeper的性能下降將會(huì)導(dǎo)致整個(gè)kafka集群的性能下降。因此勒奇,所有作為zookeeper節(jié)點(diǎn)的主機(jī)都需要擁有較大的內(nèi)存,來(lái)應(yīng)對(duì)負(fù)載的高峰巧骚。
Swap usage: 如果發(fā)現(xiàn)內(nèi)存不夠了赊颠,將會(huì)用到swap,如上文提到的那樣劈彪,這樣是不好的竣蹦,所以你必須知道它。
Disk latency:盡管zookeeper主要是使用內(nèi)存沧奴,但也會(huì)用到文件系統(tǒng)痘括,用來(lái)有規(guī)律地對(duì)當(dāng)前狀態(tài)做快照,和保存所有事務(wù)的日志滔吠。由于在update發(fā)生以后纲菌,zookeeper必須要把事務(wù)寫(xiě)到非易失的存儲(chǔ)設(shè)備上,這是的磁盤(pán)的讀寫(xiě)存在潛在瓶頸疮绷,磁盤(pán)延遲的突增翰舌,會(huì)導(dǎo)致所有與zookeeper通信的服務(wù)器響應(yīng)變慢,所以除了把zookeeper服務(wù)器的磁盤(pán)換成SSD冬骚,還需要時(shí)刻關(guān)注磁盤(pán)延遲椅贱。