Kafka 做爲一個流式數據平臺,對開發者提供了三種客戶端:生產者 / 消費者、鏈接器、流處理。本文着重分析這三種客戶端的線程模型。看到最後的一般都有驚喜。算法
消費者的線程模型sql
0.8 版本之前的消費者客戶端會建立一個基於 ZK 的消費者鏈接器,一個消費者客戶端是一個 Java 進程,消費者能夠訂閱多個主題,每一個主題也能夠多個線程。爲了讓消息在多個節點被分佈式地消費,提升消息處理的吞吐量,Kafka 容許多個消費者訂閱同一個主題,這些消費者須要知足「一個分區只能被一個消費者中的一個線程處理」的限制條件。一般,咱們會將同一份相同業務處理邏輯的應用程序部署在不一樣機器上,而且指定一個消費組編號。當不一樣機器上的消費者進程啓動後,全部這些消費者進程就組成了一個邏輯意義上的消費組。架構
消費組中的消費者數量是動態變化的,當有新消費者加入消費組,或者舊消費者離開消費組,都會觸發基於 ZK 的消費組「再平衡」操做。當「再平衡」操做發生時,每一個消費者都會在客戶端執行分區分配算法,而後從全局的分配結果中獲取屬於本身的分區。它的缺點是消費者會和 ZK 產生頻繁的交互,形成 ZK 集羣的壓力過大,而且容易產生羊羣效應和腦裂等問題。併發
在 0.8 版本之後,Kafka 從新設計了客戶端,而且引入了「協調者」和「消費組管理協議」。新的消費者將「消費組管理協議」和「分區分配策略」進行了分離。協調者負責消費組的管理,而分區分配則會在消費組的一個主消費者中完成。採用這種方式,每一個消費者都須要發送下面兩種請求給協調者。框架
加入組請求:協調者收集消費組的全部消費者,並選舉一個主消費者執行分區分配工做。分佈式
同步組請求:主消費者完成分區分配,由協調者將分區的分配結果傳播給每一個消費者。高併發
新版本的消費者客戶端引入了一個客戶端協調者的抽象類,它的實現除了消費者的協調者,還有一個鏈接器的實現。性能
鏈接器的線程模型學習
Kafka 鏈接器的出現標準化了 Kafka 與各類外部存儲系統的數據同步。用戶開發和使用鏈接器就變得很是簡單,只須要在配置文件中定義鏈接器,就能夠將外部系統的數據導入 Kafka 或將 Kafka 數據導出到外部系統。如圖 1 所示,中間部分都是 Kafka 鏈接器的內部組件,包括源鏈接器(Source Connector)和目標鏈接器(Sink Connector)。線程
圖 1 Kafka 鏈接器的源鏈接器與目標鏈接器
Kafka 鏈接器的單機模式會在一個進程內啓動一個 Worker 以及全部的鏈接器和任務。分佈式模式的每一個進程都有一個 Worker,而鏈接器和任務則分別運行在各個節點上。圖 2 列舉了鏈接器和任務在不一樣 Worker 上的四種分佈方式:
一個 Worker,一個源任務、一個目標任務
一個 Worker,兩個源任務、兩個目標任務
兩個 Worker,兩個源任務、兩個目標任務
三個 Worker,兩個源任務、兩個目標任務
圖 2 分佈式模式的 Kafka 鏈接器集羣
分佈式模式下,不一樣 Worker 進程之間的協調工做相似於消費者的協調。消費者經過協調者獲取分配的分區,Worker 也會經過協調者獲取分配的鏈接器與任務。如圖 3 所示,消費者客戶端和 Worker 客戶端爲了加入到組管理中,分別經過客戶端的協調者對象來和服務端的消費組協調(GroupCoordinator)通訊。
圖 3 消費者和 Worker 的工做都是經過協調者分配的
流處理的線程模型
Kafka 流處理的工做流程簡單來看分紅三個步驟:消費者讀取輸入分區的數據、流式地處理每條數據、生產者將處理結果寫入輸出分區,這裏面步驟 1 也充分利用了「消費組管理協議」。Kafka 流處理的輸入數據源基於具備分佈式分區模型的 Kafka 主題,它的線程模型主要由下面三個類組成:
流實例(KafkaStreams):一般一個節點(一臺機器)只運行一個流實例。
流線程(StreamThread):一個流實例能夠配置多個流線程。
流任務(StreamTask):一個流線程能夠運行多個流任務,根據輸入主題的分區數肯定任務數。
如圖 4 所示,輸入主題有六個分區,Kafka 流處理總共就會產生六個流任務。流實例能夠動態擴展,流線程的個數也能夠動態配置。圖中一共有三個流線程,則每一個流線程會有兩個流任務,每一個流任務都對應輸入主題的一個分區。
圖 4 Kafka 流處理的線程模型
Kafka 的流處理框架使用並行的線程模型處理輸入主題的數據集,這種設計思路和 Kafka 的消費者線程模型很是相似。消費者分配到訂閱主題的不一樣分區,流處理框架的流任務也分配到輸入主題的不一樣分區。如圖 5 所示,輸入主題 1 的分區 P1 和輸入主題 2 的分區 P1 分配給流線程 1 的流任務,輸入主題 1 的分區 P2 和輸入主題 2 的分區 P2 分配給流線程 2 的流任務。流處理相比消費者,還會將拓撲的計算結果寫到輸出主題。
圖 5 消費者模型與流處理的線程模型
消費者和流處理的故障容錯機制也是相似的。如圖 6 所示,假設消費者 2 進程掛掉,它所持有的分區會被分配給同一個消費組中的消費者 1,這樣消費者 1 會分配到訂閱主題的全部分區。對於流處理而言,若是流線程 2 掛掉了,流線程 2 中的流任務會分配給流線程 1。即流線程 1 會運行兩個流任務,每一個流任務分配的分區仍然保持不變。
圖 6 消費者與流處理的故障容錯機制
小 結
Kafka 客戶端抽象出來的的「組管理協議」充分運用在消費者、鏈接器、流處理三個使用場景中。客戶端中的消費者、鏈接器中的工做者、流處理中的流進程均可以看作「組」的一個成員。當增長或減小組成員時,在這個協議的約束下,每一個組成員均可以獲取到最新的任務,從而作到無縫的任務遷移。一旦理解了「組管理協議」,對於理解 Kafka 的架構設計是頗有幫助的。
歡迎工做一到五年的Java工程師朋友們加入Java架構開發: 855835163 羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!