Kafka消息體大小設置的一些細節

微信公衆號「後端進階」,專一後端技術分享:Java、Golang、WEB框架、分佈式中間件、服務治理等等。後端

還記得前幾天有個小夥伴跟我反饋發送消息時提示請求數據過大的異常嗎?通過調整 max.request.size 的大小以後,又報了了以下異常:緩存

查看相關資料後,發現 Broker 端對 Producer 發送過來的消息也有必定的大小限制,這個參數叫 message.max.bytes,這個參數決定了 Broker 可以接收到的最大消息的大小,它的默認值爲 977 KB,而 max.request.size 的值已經設置成 2M 大小了,很顯然已經比 message.max.bytes 大了不少,所以消息大於 997KB 時,就會拋出如上異常。bash

值得一提的是,主題配置也有一個參數,叫 max.message.bytes,它只針對某個主題生效,可動態配置,可覆蓋全局的 message.max.bytes,好處就是能夠針對不一樣主題去設置 Broker 接收消息的大小,並且不用重啓 Broker。微信

這還沒完,消費端拉取消息數據的大小也須要更改,這個參數叫 fetch.max.bytes,這個參數決定消費者單次從 Broker 獲取消息的最大字節數,那麼問題來了,若是該參數值比 max.request.size 小,那麼會致使消費者極可能消費不了比 fetch.max.bytes 大的消息。框架

因此綜合起來,須要這麼設置:分佈式

producer端:
max.request.size=5242880(5M)
broker:
message.max.bytes=6291456(6M)
consumer:
fetch.max.bytes=7340032(7M)

max.request.size < message.max.bytes < fetch.max.bytes
複製代碼

另外補充一點,還記得以前說過的 batch.size 參數的做用嗎,從源碼可看出,Producer 每次發送的消息封裝成 ProducerRecord,而後利用消息累加器 RecordAccumulator 添加到 ProducerBatch 中,因爲每次建立 ProducerBatch 都須要分配一個 batch.size 大小的內存空間,頻繁建立和關閉會致使性能極大開銷,因此 RecordAccumulator 內部有個 BufferPool,它實現了緩存的複用,只不過只針對 batch.size 大小的 BufferByte 進行復用,若是大於 batch.size 的 ProducerBatch,它並不會加入 BufferPool 中,也就不會複用。性能

以前有個疑問就是:假如 max.request.size 大於 batch.size,那麼該條消息會不會分多個 batch 發送到 broker?fetch

答案顯然是不會,根據上述所說,若是一個 ProducerRecord 就已經超出了 batch.size 的大小,那麼 ProducerBatch 僅包含一個 ProducerRecord,而且該 ProducerBatch 並不會加入到 BufferPool 中。spa

因此,在 Kafka Producer 調優過程當中,根據業務需求,須要特別注意 batch.size 與 max.request.size 之間的大小值的設定,避免內存空間頻繁地建立和關閉。code

公衆號「後端進階」,專一後端技術分享!

關注公衆號回覆關鍵字「後端」免費領取後端開發大禮包!

相關文章
相關標籤/搜索