kafka生產者原理分析

生產者客戶端整體架構:
在這裏插入圖片描述

​ 整個生產者客戶端由兩個線程協調運行,這兩個線程分別爲主線程和Sender線程(發送線程)。在主線程中由KafkaProducer創建消息,然後通過可能的攔截器、序列化器和分區器的作用之後緩存到消息累加器(RecordAccumulator,也稱爲消息收集器)中。Sender線程負責從RecordAccumulator中獲取消息並將其發送到kafka中。

​ RecordAccumulator主要用來緩存消息以便Sender線程可以批量發送,進而減少網絡傳輸的資源消耗以提升性能。RecordAccumulator緩存的大小可以通過生產者客戶端參數buffer.memory配置,默認值爲33554432B,即32M。如果生產者發送消息的速度超過發送到服務器的速度,則會導致生產者空間不足。這個時候KafkaProducer的send()方法調用要麼被阻塞,要麼拋出異常,這個取決於參數max.block.ms的配置,此參數的默認值爲60000,即60s。

​ 主線程發送過來的消息都會被追加到RecordAccumulator的某個雙端隊列Deque中,在RecordAccumulator的內部爲每個分區都維護了一個雙端隊列,隊列中的內容就是ProducerBatch,即Deque。消息寫入緩存時追加到雙端隊列的尾部;Sender讀取消息時,從雙端隊列的頭部讀取。ProducerBatch中可以包含一個至多個ProducerRecord,這樣可以使字節更加緊湊並且可以減少網絡請求的次數以提升整體的吞吐量。如果生產者客戶端需要向很多分區發送消息,則可以將buffer.memory參數適當調大以提升整體的吞吐量。

​ 消息在網絡上都是以字節(Byte)的形式存儲的,在發送之前需要創建一塊內存區域來保存對應的消息。在kafka生產者客戶端中,通過java.io.ByteBuffer實現消息內存的創建和釋放。不過頻繁的創建和釋放是比較耗費資源的,在RecordAccumulator的內部還有一個BufferPool,它主要用來實現ByteBuffer的複用,以實現緩存的高效利用。不過BufferPool只針對特定大小的ByteBuffer進行管理,這個大小由batch.size參數來指定,默認值爲16384B,即16KB。我們可以適當地調大參數以便可以緩存更多消息。

​ ProducerBatch的大小和batch.size參數也有密切的關係。當一條消息(ProducerRecord)流入RecordAccumulator時,會先尋找與消息分區所對應的雙端隊列(如果沒有則新建),再從這個雙端隊列的尾部獲取一個ProducerBatch(如果沒有則新建),查看ProducerBatch是否還可以寫入這個ProducerRecord,如果可以則寫入,如果不可以則需要創建一個新的ProducerBatch。在創建ProducerBatch時評估這條消息的大小是否超過batch.size,如果不超過,那麼就以batch.size的參數大小來創建ProducerBatch,這樣在使用完這塊內存區域後,可以通過BufferPool的管理來進行復用;如果超過,那麼就以評估的大小來創建ProducerBatch,這段內存區域不會被複用。


實時內容請關注微信公衆號,公衆號與博客同時更新:程序員星星
在這裏插入圖片描述

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