kafka文檔(5)----0.8.2-C/C++客戶端介紹

文章源地址:https://github.com/edenhill/librdkafka/blob/master/INTRODUCTION.md


librdkafka 是Apache  Kafka  客戶端C語言的高性能實現, 能夠提供可靠並且表現優秀的客戶端,同時它也提供比較初級的C++界面。



Contents


本文主要包含以下章節:


一、性能

-性能指標

-高吞吐量

-低延遲

-壓縮


二、消息可靠性


三、用法

-文檔介紹

-初始化

-配置

-線程和回調函數

-brokers

-producer API

-consumer API


四、其他

-測試細節




一、性能


librdkafka庫是多線程的,給現在硬件系統設計,並盡力實現最小的內存拷貝。生產或消費的消息的payload在傳輸中沒有拷貝,同時消息的尺寸沒有任何限制。


“你可能需要高吞吐率或者低延遲,但你可以擁有這兩個性能”。


librdkafka 允許你實現高吞吐率或者低延遲,這是通過可配置的屬性設置實現的。


性能指標中最重要的兩個配置屬性是:


-batch.num.messages:在發送消息序列之前,本地消息隊列中需要積累的最小消息數。

-queue.buffering.max.ms:等待batch.num.messags在本地隊列中實現的時間長度。



1、性能指標


後面的測試都是使用以下性能配置指標:


-intel  Quad  Core i7  at 3.4GHz, 8GB 內存

-通過設置brokers 刷新的配置屬性,採用簡單的方式測試硬盤性能。

       log.flush.interval.messages=10000000

      log.flush.interval.ms=100000

-兩個brokers和librdkafka都運行在同一臺機器上

-每個topic有兩個partitions

-每個broker只是一個partitions的leader

-使用子目錄example下的rdkafka_performance進行測試


測試結果(注意,原文只有producer的測試)

Test1: 2 brokers, 2 partitions, required.acks=2, 100 byte messages: 850000 messages/second, 85 MB/second


Test2: 1 broker, 1 partition, required.acks=0, 100 byte messages: 710000 messages/second, 71 MB/second


Test3: 2 broker2, 2 partitions, required.acks=2, 100 byte messages, snappy compression: 300000 messages/second, 30 MB/second


Test4: 2 broker2, 2 partitions, required.acks=2, 100 byte messages, gzip compression: 230000 messages/second, 23 MB/second


注意:本文最後將描述詳細的測試信息

注意:consumer的測試結果很快就會補上


2、高吞吐率


高吞吐率的關鍵是消息批處理實現--首先本地消息隊列中會積累一定數量的消息,然後再將這些消息一塊發送出去。這就減少了消息傳遞消耗並且減少了來回申請產生不良影響。


默認設置下: batch.num.messages=1000,queue.buffering.max.ms=1000,這有利於高吞吐率。默認設置使得librdkafka向broker發送累積消息之前,可以等待1000ms,消息最多累積1000條。這兩個屬性哪一個先滿足,就停止消息累積並進行發送,無論另一個屬性是否滿足。


這些設置雖然是全局性的(在rd_kafka_conf_t結構中實現),但是卻適用於每個top+partitions基本組成。


3、低延遲


當要求消息發送低延遲時,“queue.buffering.max.ms"應當符合producer-side延遲所允許的最大值。 queue.buffering.max.ms設置爲0將使得消息儘可能快的發送。


3、壓縮


Producer 消息壓縮通過“compression.codec配置屬性實現。


壓縮是批處理本地隊列中的消息的,批處理消息的數目越大,壓縮率越高。本地批處理隊列的容量取決於”batch.num.messages“”queue.buffering.max.ms"配置屬性,這在上邊高吞吐率章節討論。




二、消息可靠性


消息可靠性是librdkafka重要指標----實際應用中可以通過兩個特定設置(“reuqest.required.acks”和“message.send.max.retries”)保證消息可靠性。


如果topic配置屬性"request.reuired.acks“(除了0之外的其他值,查看具體細節)設置用來等待brokers收到消息的確認回覆,則librdkafka在收到所有預期acks之前會一直保存消息,這就可以很好的處理一下事件:

-brokers 連接失敗

-topic leader發生變化

-brokers通知produce錯誤


這些都是librdkafka自動完成,具體應用中無需針對以上事件做任何處理。消息在收到失敗反饋之前可以保有的時間爲”message.send.max.retires"。


librdkafka使用回調函數應對不同發送報告,即應對不同的消息發送狀態,它將在收到每條消息傳送狀態時調用響應的回調函數。

-如果error_code  非0,則消息發送失敗,error_code指明失敗原因(rd_kafka_resp_err_t enum)

-如果error_code 爲0,則消息成功發送


更多細節需要查看Producer  API章節。


發送報告的回調函數是可選的。




三、用法


1、文檔介紹

librdkafka API描述在rdkafka.h中,配置屬性描述在CONFIGURATION.md


2、初始化


實際應用中,需要創建一個top-level的對象 rd_kafka_t, 這個對象是基本的容器,它提供了全局性配置屬性以及共享狀態信息,它由rd_kafka_new()函數創建。


同時也需要創建一個或者多個topics對象rd_kafka_topic_t,給produer以及consumer使用。 topic對象具有topic特定的配置屬性,同時還包含了所有可用partitions與leader  brokers映射關係。它通過調用rd_kafka_topic_new()函數創建。


這兩個對象都包含了可配置的API。默認情況下將調用默認值,具體屬性默認值描述在CONFIGURATION.md。


注意:實際應用中,可能會創建多個rd_kafka_t對象,它們並沒有共享狀態信息

注意:rd_kafka_topic_t對象只能由創建它的對象rd_kafka_t使用。


3、配置


爲了簡化與kafka的集成以及縮短學習曲線,librdkafka實現配置屬性都可以在kafka官方客戶端中找到。


在創建對象之前,需要使用rd_kafka_conf_set()以及rd_kafka_topic_conf_set()函數進行配置。


注意: rd_kafka.._conf_t對象們在rd_kafka.._new()函數使用過後是不能被再次使用的,而且在rd_kakfa.._new()函數調用之後,不需要釋放配置資源。


例子:


rd_kafka_conf_t * conf;
char errstr[512];

conf = rd_kafka_conf_new();
rd_kafka_conf_set( conf, "compression.codec", "snappy", errstr, sizeof(errstr));
rd_kafka_conf_set( conf, "batch.num.messages", "100", errstr, sizeof(errstr));

rd_kafka_new(RD_KAFKA_PRODUCER,conf);


4、線程和回調函數


librdkafka 內部將會有多個線程,以充分利用硬件資源。API的實現是完全線程安全的,實際應用中可以在任何時候任何線程中調用任何API函數而不用擔心線程安全。


一個以輪詢爲基礎的API用來給實際應用提供信號反饋,實際應用應當按照固定時間間隔調用rd_kafka_poll()函數。這個輪詢的API將會調用以下可的回調(都是可選的):


-消息發送報告回調:報告消息發送失敗。這將允許實際應用採取措施應對發送失敗,並釋放消息發送過程中佔有的資源。


-錯誤回調:報告錯誤;錯誤一般是信息化方面的,例如連接broker失敗,實際應用通常不需要採取任何措施。錯誤的數據類型是通過rd_kafka_resp_err_t enum類型數據,可以描述本地錯誤和遠程broker錯誤。


不是poll函數引起的可選回調函數,可能是由任意線程引發的:


-logging 回調:實際應用中,用於發送librdkafka產生的log消息。

-partitioner 回調:實際應用提供消息的partitioner。partitioner可能被任何線程任何時候調用,它可能由於同一個key而被調用多次。Partitioner 函數有以下限制:

     一定不能調用rd_kafka_*()等函數

     一定不能阻塞或延長執行

      一定要返回一個0到partition_cnt-1之間的值,或者是在partitioning不能執行的時候返回特定RD_KAFKA_PARTITION_UA值,


5、Brokers


librdkafka 只需要一份最初的brokers列表(至少包含一個broker)。它將連接所有"metadata.broker.list"或者是rd_kafka_brokers_add()函數添加的brokers,然後向每個brokers申請一些元數據信息:包含brokers的完整列表、topic、partitions以及它們在Kafka 集羣中的leaders broker信息。


Brokers名字的形式爲:host:port; 其中port是可選的,默認是9092,host是任何一個可以解析的hostname或者ipv4或者ipv6地址。如果host是多個地址,librdkafka將會在每一次連接嘗試中循環連接這些地址。包含所有broker 地址的DNS記錄可以用來提供可靠的bootstrap broker。



6、Producer  API


在使用RD_KAFKA_PRODUCER設置完rd_kafka_t對象後,就可以創建一個或者多個rd_kafka_topic_t對象了,用來接受信息或者發送信息。


rd_kafka_produce()函數需要以下參數:

-rkt: topic, 由前面rd_kafka_topic_new()函數創建

-partition:partition,如果爲RD_KAFKA_PARTITION_UA,則配置的partitioner函數將會選擇目標partition

-payload,len: 消息主體

-msgflags:0或者以下數值之一:

                   RD_KAFKA_MSG_F_COPY: librdkafka 在發送前先將消息拷貝下來,以防消息主體所在的緩存不是長久使用的,例如堆棧。

                   RD_KAFKA_MSG_F_FREE: librdkafka 在使用完消息後,將釋放消息緩存。

                   這兩個標誌是互斥的,只能設置一個,用來表示是拷貝還是釋放。

                    

                    如果沒有設置RD_KAFKA_MSG_F_COPY標誌,則沒有數據拷貝,librdkafka將會佔有消息payload指針直到消息發送完畢或者失敗。發送報告回調函數將會在librdkafka使實際調用重新獲得payload緩存控制權的時候被調用。在RD_KAFKA_MSG_F_FREE設置的時候,實際調用一定不能在發送報告回調函數中釋放payload。


-key,keylen: 可選參數,消息關鍵字,可以用來分區。它將會傳遞到topic partitioner回調中,如果存在,則會添加到發向broker的消息中。

-msg_opaque:可選參數,每條消息的透明度指針,由消息傳送回調所提供,使應用參考特定的消息。


rd_kafka_produce()是非阻塞的API, 它將使消息存儲在內部隊列中並立即返回。如果入隊的消息數目超過了配置的“queue.buffering.max.messages"屬性,則rd_kafka_produce()函數將會返回-1並將errno設置爲ENOBUFS, 這樣就提供了應對壓力的機制。


注意:examples/rdkafka_performance.c提供了producer的實現。



7、Consumer  API


consumer API要比producer  API多一些狀態。 在使用RD_KAFKA_CONSUMER類型創建rd_kafka_t 對象,然後創建rd_kakfa_topic_t對象之後,實際應用中必須調用rd_kafka_consumer_start()函數啓動對給定partition的consumer。


rd_kafka_consume_start()函數的參數:

-rkt: 進行consume的topic, 由前面rd_kafka_topic_new()創建

-partition:進行consume的partition

-offset:開始consume的消息偏移。這個偏移可能是一個絕對消息偏移,或者是RD_KAKFA_OFFSET_STORED來使用存儲的offset,也可能是兩個特定偏移之一:RD_KAFKA_OFFSET_BEGINNING,從partition消息隊列的開始進行consume;RD_KAFKA_OFFSET_END:從partition中的將要produce的下一條信息開始(忽略即當前所有的消息)。


在topic+partition的consumer啓動之後,librdkafka將嘗試使本地消息隊列中的消息數目保持在queued.min.messages,一方反覆的從broker獲取消息。


本地消息隊列將通過以下三種不同的consum  APIs進行consume:

-rd_kafka_consume():每次consume一條消息

-rd_kafka_consume_batch():批處理consume,一條或多條

-rd_kafka_consume_callback():consume本地消息隊列中的所有消息,並調用回調函數處理每條消息


上述三種方式按照性能排列的,rd_kafka_consume()是最慢的,rd_kafka_consume_callback()最快。不同的需求可以選擇不同的實現方式。


一條consumed消息,由每一個consume函數提供或返回,具體是由rd_kafka_messag_t類型對象保存。


rd_kafka_message_t對象成員:

-err:錯誤返回值。非0值表示出現錯誤,err是rd_kafka_resp_err_t類型數據。如果是0則表示進行了適當的消息抓取,並且payload中包含了message。

-rkt,partition:topic和partition信息

-payload,len:消息的payload數據或者錯誤的消息(err!=0)

-key,key_len:可選參數,主要是用來獲取特定的消息。

-offset:消息的偏移地址


payload,key和消息一樣,都是屬於librdkafka,在rd_kafka_message_destroy()函數調用之後就不能再使用了。librdkafka將會使用相同的消息集接收緩存來存放消息消息集的playloads,這就避免過度拷貝,即意味着如果實際應用決定掛起某個單獨的rd_kafka_message_t對象,這將會阻礙後面的緩存釋放。


當實際應用完成consume消息,則應該調用rd_kafka_consume_stop()函數停止consumer。這將消除本地隊列中中任何消息。


注意:examples/rdkafka_performance.c實現了consumer。



8、offset 管理


Offset管理可以通過本地offset保存文件完成,offset將會週期性的寫入每個topic+partition的配置屬性:

-auto.commit.enable

-auto.commit.interval.ms

-offset.store.path

-offset.store.sync.interval.ms


當前ZooKeeper還不支持offset管理。


9、Consumer  groups


當前還不支持consumer  groups, librdkafka consumer  API只編譯了官方scala 簡單版的Consumer。只有librdkafka能夠支持這項應用,你才能擁有你的消費組。



10、Topics

Topic自動創建

topic自動創建是支持的。brokers需要使用”auto.create.topics.enable=true“進行配置。



四、其他:


測試細節:

Test1: Produce to two brokers, two partitions, required.acks=2, 100 byte messages

Each broker is leader for one of the two partitions. The random partitioner is used (default) and each broker and partition is assigned approximately 250000 messages each.

Command:

# examples/rdkafka_performance -P -t test2 -s 100 -c 500000 -m "_____________Test1:TwoBrokers:500kmsgs:100bytes" -S 1 -a 2
....
% 500000 messages and 50000000 bytes sent in 587ms: 851531 msgs/s and 85.15 Mb/s, 0 messages failed, no compression

Result:

Message transfer rate is approximately 850000 messages per second85 megabytes per second.

Test2: Produce to one broker, one partition, required.acks=0, 100 byte messages

Command:

# examples/rdkafka_performance -P -t test2 -s 100 -c 500000 -m "_____________Test2:OneBrokers:500kmsgs:100bytes" -S 1 -a 0 -p 1
....
% 500000 messages and 50000000 bytes sent in 698ms: 715994 msgs/s and 71.60 Mb/s, 0 messages failed, no compression

Result:

Message transfer rate is approximately 710000 messages per second71 megabytes per second.

Test3: Produce to two brokers, two partitions, required.acks=2, 100 byte messages, snappy compression

Command:

# examples/rdkafka_performance -P -t test2 -s 100 -c 500000 -m "_____________Test3:TwoBrokers:500kmsgs:100bytes:snappy" -S 1 -a 2 -z snappy
....
% 500000 messages and 50000000 bytes sent in 1672ms: 298915 msgs/s and 29.89 Mb/s, 0 messages failed, snappy compression

Result:

Message transfer rate is approximately 300000 messages per second30 megabytes per second.

Test4: Produce to two brokers, two partitions, required.acks=2, 100 byte messages, gzip compression

Command:

# examples/rdkafka_performance -P -t test2 -s 100 -c 500000 -m "_____________Test3:TwoBrokers:500kmsgs:100bytes:gzip" -S 1 -a 2 -z gzip
....
% 500000 messages and 50000000 bytes sent in 2111ms: 236812 msgs/s and 23.68 Mb/s, 0 messages failed, gzip compression

Result:

Message transfer rate is approximately 230000 messages per second23 megabytes per second.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章