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

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

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

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

值得一提的是,主題配置也有一個參數,叫 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?

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

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

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

關注公衆號回覆關鍵字「後端」免費領取後端開發大禮包!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章