本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。期待加入IOT時代最具戰鬥力的團隊。QQ郵箱地址:1120746959@qq.com,如有任何學術交流,可隨時聯絡。
1 Producer端基本資料結構
-
ProducerRecord: 一個ProducerRecord表示一條待傳送的訊息記錄,主要由5個欄位構成:
topic 所屬topic partition 所屬分割槽 key 鍵值 value 訊息體 timestamp 時間戳 複製程式碼
-
RecordMetadata: Kafka伺服器端返回給客戶端的訊息的後設資料資訊,前3項相對比較重要,Producer端可以使用這些訊息做一些訊息傳送成功之後的處理。
offset 該條訊息的位移 timestamp 訊息時間戳 topic + partition 所屬topic的分割槽 checksum 訊息CRC32碼 serializedKeySize 序列化後的訊息鍵位元組數 serializedValueSize 序列化後的訊息體位元組數 複製程式碼
2 Producer端訊息傳送流程
-
在send()的傳送訊息動作觸發之前,通過props屬性中指定的servers連線到broker叢集,從Zookeeper收集叢集Metedata資訊,從而瞭解哪些broker掌管哪一個Topic的哪一個partition,以及brokers的健康狀態。
-
下面就是流水線操作,ProducerRecord物件攜帶者topic,partition,message等資訊,在Serializer這個“車間”被序列化。
-
序列化過後的ProducerRecord物件進入Partitioner“車間”,按照上文所述的Partitioning 策略決定這個訊息將被分配到哪個Partition中。
-
確定partition的ProducerRecord進入一個緩衝區,通過減少IO來提升效能,在這個“車間”,訊息被按照TopicPartition資訊進行歸類整理,相同Topic且相同parition的ProducerRecord被放在同一個RecordBatch中,等待被髮送。什麼時候傳送?都在Producer的props中被指定了,有預設值,顯然我們可以自己指定。
(1) batch.size:設定每個RecordBatch可以快取的最大位元組數 (2) buffer.memory:設定所有RecordBatch的總共最大位元組數 (3) linger.ms設定每個RecordBatch的最長延遲傳送時間 (4) max.block.ms 設定每個RecordBatch的最長阻塞時間 複製程式碼
-
一旦,當單個RecordBatch的linger.ms延遲到達或者batch.size達到上限,這個 RecordBatch會被立即傳送。另外,如果所有RecordBatch作為一個整體,達到了buffer.memroy或者max.block.ms上限,所有的RecordBatch都會被髮送。
-
ProducerRecord訊息按照分配好的Partition傳送到具體的broker中,broker接收儲存訊息,更新Metadata資訊,同步給Zookeeper。
-
Producer端其他優化點:
(5) acks:Producer的資料確認阻塞設定,0表示不管任何響應,只管發,發完了立即執行下個任務,這種方式最快,但是很不保險。1表示只確保leader成功響應,接收到資料。2表示確保leader及其所有follwer成功接收儲存訊息,也可以用”all”。 (6) retries:訊息傳送失敗重試的次數。 (7) retry.backoff.ms:失敗補償時間,每次失敗重試的時間間隔,不可設定太短,避免第一條訊息的響應還沒返回,第二條訊息又發出去了,造成邏輯錯誤。 (8) max.in.flight.request.per.connection:同一時間,每個Producer能夠傳送的訊息上限。 (9) compression.type producer所使用的壓縮器,目前支援gzip, snappy和lz4。壓縮是在使用者主執行緒完成的,通常都需要花費大量的CPU時間,但對於減少網路IO來說確實利器。生產環境中可以結合壓力測試進行適當配置 複製程式碼
3 訊息緩衝區(accumulator)再剖析
-
producer建立時會建立一個預設32MB(由buffer.memory引數指定)的accumulator緩衝區,專門儲存待傳送的訊息。
-
該資料結構中還包含了一個特別重要的集合資訊:訊息批次資訊(batches)。該集合本質上是一個HashMap,裡面分別儲存了每個topic分割槽下的batch佇列,即前面說的批次是按照topic分割槽進行分組的。這樣發往不同分割槽的訊息儲存在對應分割槽下的batch佇列中。
-
假設訊息M1, M2被髮送到test的0分割槽但屬於不同的batch,M3分送到test的1分割槽,那麼batches中包含的資訊就是:{"test-0" -> [batch1, batch2], "test-1" -> [batch3]}
-
每個batch中最重要的3個元件包括:
compressor: 負責執行追加寫入操作 batch緩衝區:由batch.size引數控制,訊息被真正追加寫入到的地方 thunks:儲存訊息回撥邏輯的集合 複製程式碼
-
本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。期待加入IOT時代最具戰鬥力的團隊。QQ郵箱地址:1120746959@qq.com,如有任何學術交流,可隨時聯絡。
-
Sender執行緒自KafkaProducer建立後就一直都在執行著 。它的工作流程基本上是這樣的:
(1)不斷輪詢緩衝區尋找已做好傳送準備的分割槽 (2)將輪詢獲得的各個batch按照目標分割槽所在的leader broker進行分組 (3)將分組後的batch通過底層建立的Socket連線傳送給各個broker (4)等待伺服器端傳送response回來 複製程式碼
- Sender執行緒會傳送PRODUCE請求給對應的broker,broker處理完畢之後傳送對應的PRODUCE response。一旦Sender執行緒接收到response將依次(按照訊息傳送順序)呼叫batch中的回撥方法
4 總結
- Sender執行緒自KafkaProducer建立後就一直都在執行著,單個RecordBatch的linger.ms延遲到達或者batch.size達到上限,作為後臺執行緒就會檢測到立即傳送。
- accumulator緩衝器按照Topic partion進行分組,來進行集中向某一個Broker傳送。
- 本文通過學習胡夕的相關技術部落格和書籍,進行的學習筆記總結,辛苦成文,實屬不易,各自珍惜,謝謝。
- 秦凱新 於深圳 201812030018