十張圖片和五個問題可以讓你對Kafka架構的調優有一個全面的了解。
十張圖片和五個問題,讓你徹底了解Kafka架構調優 今天,我將和大家分享一下Kafka架構調優的技巧。 本文有很多幹貨,希望大家能耐心看完。 1 你知道Kafka的超高並發網絡架構是如何設計的嗎? 我們知道,Kafka的網絡通信架構采用了Java NIO和Reactor設計模式。 我們先來看看完整的網絡通信層架構的整體情況,如下圖所示。 1)從上圖中我們可以看出,Kafka網絡通信架構中使用的組件主要由兩部分組成。SocketServer和RequestHandlerPool。 2)SocketServer組件是Kafka的超高並發網絡通信層中最重要的子模塊。 它包含諸如Acceptor線程、Processor線程和RequestChannel等對象,這些都是網絡通信的重要組成部分。 3)RequestHandlerPool組件就是我們常說的I/O工作者線程池,它定義了幾個I/O線程,主要用於執行真正的請求處理邏輯。 01 接受線程 在經典的Reactor設計模式中,有一個 "Dispatcher "角色,主要用於接收外部請求,並將其分發給下面的實際處理線程。 在Kafka網絡架構設計中,這個Dispatcher就是 "Acceptor線程",一個用來接收和創建外部TCP連接的線程。 在Broker端,每個SocketServer實例只創建一個Acceptor線程。 它的主要功能是創建一個連接,並將收到的Request請求傳遞給下遊的Processor線程進行處理。 1)我們可以看到,Acceptor線程主要使用Java NIO的Selector和SocketChannel來循環和輪詢準備好的I/O事件。 2 ) 將ServerSocketChannel通道註冊到nioSelector,並註意網絡連接創建事件。 SelectionKey.OP_ACCEPT。 3) 事件註冊後,一旦隨後收到連接請求,Acceptor線程將指定一個Processor線程,將請求交給它,並創建一個網絡連接進行後續處理。 02 處理器線程 Acceptor只處理請求入口的連接,所以真正創建網絡連接和分配網絡請求的工作是由Processor線程完成。 而每個Processor線程在創建時都會創建3個隊列。 1)newConnections隊列:主要用於保存要創建的新連接信息,也就是SocketChannel對象。目前,硬編碼隊列的長度是20。 每當Processor線程收到一個新的連接請求時,它就會把相應的SocketChannel對象放入隊列中,以後創建連接時,從隊列中獲取SocketChannel,然後再註冊新的連接。 2) inflightResponse隊列。它是一個臨時的Response隊列。當處理器線程將Repsonse返回給客戶端時,它將把Response放入隊列。 它存在的意義。因為一些Response回調邏輯在Response被送回給Request發送者之前不能被執行,所以需要暫時存放在一個臨時隊列中。 3) ResponseQueue隊列。它主要存儲所有需要返回給請求發送者的Response對象。 每個處理器線程都維護自己的Response隊列。 03 RequestHandlerPool線程池 Acceptor線程和Processor線程只是請求和響應的 "搬運工",而 "真正處理Kafka請求 "的是KafkaRequestHandlerPool線程池。 在上述網絡高並發通信架構圖中,有兩個參數與整個流程相關,即 "num.network.threads"、"num.io.threads"。 其中num.io.threads是I/O工作者線程池的大小配置。 讓我們結合Kafka超高並發網絡架構圖來解釋接下來完整的請求處理核心流程。 1)客戶端向Acceptor線程發送請求。 2)Acceptor線程創建NIO Selector對象,創建ServerSocketChannel實例,並將Channel和OP_ACCEPT事件綁定到Selector復用器上。 3) Acceptor線程默認創建3個Processor線程參數:num.network.threads,並將請求對象SocketChannel輪詢到連接隊列中。 4)此時,連接隊列有穩定的請求數據流,然後連續執行NIO Poll,以獲得相應SocketChannel上準備好的I/O事件。 5)處理器線程將OP_READ/OP_WRITE事件註冊到SocketChannel上,這樣客戶端發送的請求就會被SocketChannel對象獲得,具體來說就是processCompleteReceives方法。