這裡編譯 Kafka 的版本是 2.7,為啥採用這個版本來搭建源碼的閱讀環境呢?因為該版本相對來說比較新。而我為啥不用 2.7 後的版本呢?比如 2.8,這是因為去掉了 ZooKeeper,還不太穩定,生產環境也不太建議使用,所以以 2.7 版本進行源碼搭建並研究。
二、環境準備JDK:1.8.0_241
Scala:2.12.8
Gradle:6.6
Zookeeper:3.4.14
三、環境搭建3.1 JDK 環境搭建
這個就不用我說了吧,搞 Java 的本機都有 JDK 環境。
3.2 Scala 環境搭建
下載連結:https://www.scala-lang.org/download/2.12.8.html
這裡老周是 Mac OS 系統,這裡大家看著自己的系統來下就好了哈。
3.2.1 配置 Scala 環境變量
終端輸入以下命令進行編輯:
vim ~/.bash_profile
# 這裡的路徑是你安裝
SCALA_HOME=/Users/Riemann/Tools/scala-2.12.8
export SCALA_HOME
export PATH=$PATH:$SCALA_HOME/bin
# 使環境變量生效,在命令行執行。
source ~/.bash_profile
3.2.2 驗證
終端輸入以下命令:
scala -version
出現以下提示,說明 Scala 環境搭建成功。
3.3 Gradle 環境搭建
首先來到 Gradle官網:https://services.gradle.org/distributions/
如下圖:
Gradle下載的源碼不需要安裝,我們將下載的壓縮包在本機的目錄下直接解壓即可,解壓後的目錄如下圖所示。
3.3.1 配置 Gradle 環境變量
終端輸入以下命令進行編輯:
vim ~/.bash_profile
# 這裡的路徑是你安裝
GRADLE_HOME=/Users/Riemann/Tools/gradle-6.6
export GRADLE_HOME
export PATH=$PATH:$GRADLE_HOME/bin
# 使環境變量生效,在命令行執行。
source ~/.bash_profile
3.3.2 驗證
終端輸入以下命令:
gradle -v
出現以下提示,說明 Gradle 環境搭建成功。
Zookeeper 環境老周在 Linux 環境已經搭建好了的,直接用。這裡我也給出搭建的步驟,不管你是啥系統,都是類似的~
3.4.1 下載
wget http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
3.4.2 解壓
tar -zxvf zookeeper-3.4.14.tar.gz
3.4.3 進入 zookeeper-3.4.14 目錄,創建 data 文件夾
cd zookeeper-3.4.14
mkdir data
3.4.4 修改配置文件
cd conf
mv zoo_sample.cfg zoo.cfg
3.4.5 修改 zoo.cfg 中的 data 屬性
dataDir=/root/zookeeper-3.4.14/data
3.4.6 zookeeper 服務啟動
進入 bin 目錄,啟動服務輸入命令
./zkServer.sh start
輸出以下內容表示啟動成功
3.5 Kafka 源碼環境搭建
官網下載對應版本的源碼包,網址:http://kafka.apache.org/downloads
3.5.1 導入 Kafka 源碼至 IDEA
接下來還不能導 jar 包,需要把鏡像文件下載伺服器更換為國內的私服,否則會相當慢,直接導致 "time out" 報錯。
進入 kafka 源碼包,修改 build.gradle 文件,在原來配置上,添加 ali 私服配置。
buildscript {
repositories {
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
maven {
url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'
}
}
}
allprojects {
repositories {
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
maven {
url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'
}
}
}
可以用命令來構建,也可以在 idea 圖形界面的 gradle 來構建,這裡肯定是 idea 圖形化界面操作更簡單,但這裡也提供 gradle 的命令來構建。
./gradlew clean build -x test
去找一下直接下載 Wrapper 所需的 Jar 包,手動把這個 Jar 文件拷貝到 kafka 路徑下的 gradle/wrapper 子目錄下,然後重新執行 gradlew build 命令去構建工程。
連結: https://pan.baidu.com/s/1W6EHysWY3ZWQZRWNdNZn3Q 提取碼: hpj5
gradle 其它命令:
# 構建 jar包並運行
./gradlew jar
# 構建項目,看你是idea工具還是eclipse
./gradlew idea
./gradlew eclipse
# 構建源碼包
./gradlew srcJar
# 構建javadoc文檔
./gradlew aggregatedJavadoc
# 清理並構建
./gradlew clean
4.1 代碼安裝包結構
bin 目錄:保存 Kafka 工具行腳本,我們熟知的 kafka-server-start 和 kafka-console-producer 等腳本都存放在這裡。
checkstyle 目錄:代碼規範,自動化檢測。
Checkstyle 是什麼,關于格式化的討論就不曾中斷過,到底什麼才是正確的,什麼才是錯誤的,到現在也沒有完整的定論。但隨著時間發展,漸漸衍生出一套規範出來。沒有什麼絕對的正確和錯誤,關鍵在於規範的定義。最出名的就是 google style guide,Checkstyle 就是以這種風格開發出的一個自動化插件,來輔助判斷代碼格式是否滿足規範。
該目錄下的文件定義了工程代碼格式的規範,我們可以在 build.gradle 中看到相關 checkstyle 的配置和自動化代碼格式化配置:
checkstyle 配置:
scala 自動化代碼格式化配置:
clients 目錄:保存 Kafka 客戶端代碼,比如生產者和消費者的代碼都在該目錄下。
config 目錄:保存 Kafka 的配置文件,其中比較重要的配置文件是 server.properties。
connect 目錄:保存 Connect 組件的原始碼。Kafka Connect 組件是用來實現 Kafka 與外部系統之間的實時數據傳輸的。
core 目錄:保存 Broker 端代碼。Kafka 伺服器端代碼全部保存在該目錄下。
docs 目錄:Kafka 設計文檔以及組件相關結構圖。
examples 目錄:Kafka 樣例相關目錄。
generator 目錄:Kafka 消息類處理模塊,主要是根據 clients 模塊下的 message json 文件生成對應的 java 類,在 build.gradle 文件中,可以看到定義了一個任務 processMessages:
gradle 目錄:gradle 的腳本和依賴包定義等相關文件。
jmh-benchmarks 目錄:Kafka 代碼微基準測試相關類。
JMH,即 Java Microbenchmark Harness,是專門用於代碼微基準測試的工具套件。何謂 Micro Benchmark 呢?簡單的來說就是基於方法層面的基準測試,精度可以達到微秒級。當你定位到熱點方法,希望進一步優化方法性能的時候,就可以使用 JMH 對優化的結果進行量化的分析。
JMH 比較典型的應用場景有:
kafka-logs 目錄:server.properties 文件中配置 log.dirs 生成的目錄。
log4j-appender 目錄:
A log4j appender that produces log messages to Kafka
這個目錄裡面就一個 KafkaLog4jAppender 類。
raft 目錄:raft 一致性協議相關。
streams 目錄:
Kafka Streams is a client library for building applications and microservices, where the input and output data are stored in Kafka clusters.
提供一個基於 Kafka 的流式處理類庫,直接提供具體的類給開發者調用,整個應用的運行方式主要由開發者控制,方便使用和調試。
Kafka Streams 是一個用來構建流處理程序的庫,特別是其輸入是一個 Kafka topic,輸出是另一個 Kafka topic 的程序(或者是調用外部服務,或者是更新資料庫,或者其它)。它使得你以一種分布式以及容錯的方式來做這件事情。
tests 目錄:此目錄的內容介紹如何進行 Kafka 系統集成和性能測試。
tools 目錄:工具類模塊。
vagrant 目錄:介紹如何在 Vagrant 虛擬環境中運行 Kafka,提供了相關的腳本文件和說明文檔。
Vagrant 是一個基於 Ruby 的工具,用於創建和部署虛擬化開發環境。它使用 Oracle 的開源 VirtualBox 虛擬化系統,使用 Chef 創建自動化虛擬環境。
4.2 項目結構
項目結構的話主要關注 core 目錄,core 目錄 是 Kafka 核心包,有集群管理,分區管理,存儲管理,副本管理,消費者組管理,網絡通信,消費管理等核心類。
admin 包:執行管理命令的功能;
api 包:封裝請求和響應 DTO 對象;
cluster 包:集群對象,例如 Replica 類代表一個分區副本,Partition 類代表一個分區;
common 包:通用 jar 包;
controller包:和kafkaController(kc)相關的類,重點模塊,一個kafka集群只有一個leader kc,該kc負責 分區管理,副本管理,並保證集群信息在集群中同步;
coordinator 包:保存了消費者端的 GroupCoordinator 代碼和用於事務的 TransactionCoordinator 代碼。對 coordinator 包進行分析,特別是對消費者端的 GroupCoordinator 代碼進行分析,是 Broker 端協調者組件設計原理的關鍵。
log 包:保存了 Kafka 最核心的日誌結構代碼,包括日誌、日誌段、索引文件等, 另外,該包下還封裝了 Log Compaction 的實現機制,是非常重要的源碼包。
network 包:封裝了 Kafka 伺服器端網絡層的代碼,特別是 SocketServer.scala 這個文件,是 Kafka 實現 Reactor 模式的具體操作類,非常值得一讀。
consumer 包:後面會丟棄該包,用 clients 包下 consumer 相關類代替。
server 包:顧名思義,它是 Kafka 的伺服器端主代碼,裡面的類非常多,很多關鍵的 Kafka 組件都存放在這裡,比如狀態機、Purgatory 延時機制等。
tools 包:工具類。
五、環境驗證下面我們來驗證一下 Kafka 源碼環境是否搭建成功。
5.1 首先,我們在 core/src/main 目錄下新建 resources 目錄,再將 conf 目錄下的 log4j.properties 配置文件拷貝到 resources 目錄下。
如下圖所示:
log.dirs=/Users/Riemann/Code/framework-source-code-analysis/kafka-2.7.0-src/kafka-logs
server.properties 文件中的其他配置暫時不用修改。
5.3 在 IDEA 中配置 kafka.Kafka 這個入口類
具體配置如下圖所示:
啟動成功的話,控制臺輸出沒有異常,且能看到如下輸出:
5.5 可能出現以下異常
5.5.1 異常1
log4j:WARN No appenders could be found for logger (kafka.utils.Log4jControllerRegistration$).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
在 project structure 中加入 slf4j-log4j12-1.7.30.jar 和 log4j-1.2.17.jar 兩個日誌包,當然也可以在 build.gradle 中添加對應的配置來添加包。
方法1: