Kafka 入門與實踐

蔚1發表於2018-04-12

內容簡介

本書以 Kafka 0.10.1.1 版本以基礎,對 Kafka 的基本元件的實現細節及其基本應用進行了詳細介紹,同時,通過對 Kafka 與當前大資料主流框架整合應用案例的講解,進一步展現了 Kafka 在實際業務中的作用和地位。按照從抽象到具體、從點到線再到面的學習思維模式,由淺入深,理論與實踐相結合,對 Kafka 進行了分析講解。

本書中的大量例項來源於作者在實際工作中的實踐,具有現實指導意義。相信讀者閱讀完本書之後,能夠全面掌握 Kafka 的基本實現原理及其基本操作,能夠根據書中的案例舉一反三,解決實際工作和學習中的問題。此外,在閱讀本書時,讀者可以根據本書對 Kafka 理論的分析,再結合 Kafka 原始碼進行定位學習,瞭解 Kafka 優秀的設計和思想以及更多的編碼技巧。

本書適合應用 Kafka 的專業技術人員閱讀,包括但不限於大資料相關應用的開發者、運維者和愛好者,也適合高等院校、培訓結構相關專業的師生使用。

作者簡介

牟大恩,武漢大學碩士,曾先後在網易杭州研究院、掌門科技、優酷土豆集團擔任高階開發工程師和資深開發工程師職務,目前就職於海通證券總部。有多年的 Java 開發及系統設計經驗,專注於網際網路金融及大資料應用相關領域。

本書內容

前言

為什麼要寫這本書

Kafka 由於高吞吐量、可持久化、分散式、支援流資料處理等特性而被廣泛應用。但當前關於 Kafka 原理及應用的相關資料較少,在我打算編寫本書時,還沒有見到中文版本的 Kafka 相關書籍,對於初學者甚至是一些中高階應用者來說學習成本還是比較高的,因此我打算在對 Kafka 進行深入而系統的研究基礎上,結合自己在工作中的實踐經驗,編寫一本介紹 Kafka 原理及其基本應用的書籍,以幫助 Kafka 初、中、高階應用者更快、更好地全面掌握 Kafka 的基礎理論及其基本應用,從而解決實際業務中的問題。同時,一直以來我都考慮在技術方面寫點什麼,將自己所學、所積累的知識沉澱下來。

通過編寫本書,我最大收穫有如下兩點。

第一,凡事不是要盡力而為,而是要全力以赴,持之以恆。寫書和閱讀原始碼其實都是很枯燥的事,理工科出身的我,在文字表達能力上還是有所欠缺的,有些知識點可能在腦海裡十分清晰,然而當用文字表述出來時,就顯得有些“力不從心”了。對於純技術的東西要用讓讀者閱讀時感覺輕鬆的文字描述出來更是不易,因此看似簡短的幾行文字,我在編寫時可能斟酌和修改了很久。我真的很欽佩那些大師們,他們寫出來的東西總讓人很輕鬆地就能夠掌握,“路漫漫其修遠兮,吾將上下而求索”,向大師們致敬!雖然有很多客觀或主觀的因素存在,但我依然沒有放棄。還記得2016年10月的一天,當我決定編寫本書時,我告訴妻子:“我要寫一本書作為送給我們未來寶寶的見面禮!”帶著這份動力我利用下班時間、週末時間,在夜深人靜時默默地進行著Kafka相關內容的研究、學習、實戰,妻子對我的鼓勵、陪伴更是激勵我要堅持本書的編寫。帶著這份動力,帶著這份愛,我終於完成了本書。

第二,通過對 Kafka 原始碼的閱讀,我除了對很多原來在實踐中只知其然而不知其所以然的問題有了更深入的理解以外,還對 Kafka 優秀的設計思想及其編碼技巧有所瞭解。

如何閱讀本書

本書共10章,各章主要內容具體描述如下。

第1章對 Kafka 的基本概念進行簡要介紹,方便讀者對 Kafka 有一個大致的瞭解。

第2章詳細介紹 Kafka 安裝環境的配置及 Kafka 原始碼的編譯,這一章為後續各章的 Kafka 原理講解及基本操作進行準備。

第3章對 Kafka 基本元件的實現原理、實現細節進行了分析。如果只想瞭解 Kafka 的相關應用,而不關注 Kafka 的實現原理,在閱讀時可以直接跳過這一章。但我覺得,如果想真正掌握 Kafka 及其實現細節,這一章是值得花時間仔細閱讀的。

第4章對 Kafka 核心流程進行分析,主要從 Kafka 啟動流程到建立一個主題、生產者傳送訊息、消費者消費訊息的過程進行了簡要介紹。這一章是 Kafka 執行機制的縮影,如果跳過了第3章關於元件實現原理的講解,那麼建議一定要閱讀這一章,因為通過閱讀這一章可以更進一步地瞭解 Kafka 執行時的主要角色及其職責,為後面的 Kafka 實戰部分打下堅實基礎。

第5章開始就進入了 Kafka 實戰部分。這一章通過 Kafka 自帶指令碼演示,詳細介紹了 Kafka 基本應用的操作步驟,基本覆蓋了 Kafka 相關操作,因此請讀者在閱讀時要跟隨本書所講內容進行實戰。

第6章對 Kafka 的 API 應用進行了詳細介紹。如果讀者在實踐工作中不會用到呼叫 Kafka 的相關 API,在閱讀時也可以跳過這一章。

第7章對 Kafka Streams 進行了介紹。Kafka Streams 是 Kafka 新增的支援流資料處理的 Java庫。如果讀者不希望使用此功能,也可以跳過這一章。

第8章介紹 Kafka 在資料採集方面的應用,主要包括與 Log4j、Flume 和 HDFS 的整合應用。

第9章對 Kafka 與 ELK(Elasticsearch、Logstash 和 Kibana)整合實現日誌採集平臺相關應用進行介紹。

第10章通過兩個簡單的例項,介紹了 Spark 以及 Kafka 與 Spark 整合在離線計算、實時計算方面的應用。

本書的結構安排上,各章的內容相互獨立,因此讀者可以首先選擇自己最感興趣的章進行閱讀,之後再閱讀其他章。例如,讀者可以先閱讀第5章及其之後的幾章,先通過實踐操作對 Kafka 有一個感性的認識,然後再閱讀第3章和第4章的相關原理及執行機制的內容,逐步加深對 Kafka 實現細節的理解。而第8章至第10章則是 Kafka 與當前大資料處理主流框架的整合應用,屬於 Kafka 高階應用部分,可以幫助讀者解決實際業務問題。

我建議讀者一定要閱讀第2章。通過第2章介紹的環境配置,讀者能自己在本地搭建 Kafka 執行環境,閱讀本書時,可跟隨本書所講解的操作進行實踐。

讀者物件

本書的目標讀者定位是應用 Kafka 的初、中、高階開發人員及運維工程師。

從事 Kafka 應用開發的技術人員讀完本書,可以學習到 Kafka 原理的分析及相關 API 應用以及結合當前主流大資料框架整合的應用,應該能夠全面掌握 Kafka 的基本原理和整體結構,併為實際業務實現提供思路,從而能夠更加快速地解決一些問題。

從事 Kafka 或資料運維的技術人員,讀完本書詳細的 Kafka 基本操作以及 Kafka 與其他大資料框架的整合應用案例,應該可以快速搭建、運維和管理 Kafka 及相應的系統平臺。

從事 Kafka 相關應用的資深開發或架構人員,讀完本書對 Kafka 原理的分析有助於對 Kafka 效能進行調優,可以更好地開發和設計與 Kafka 相關的應用。

對於初學者,通過閱讀本書可以全面掌握 Kafka 的知識,同時可以通過 Kafka 與其他框架整合的案例來拓寬視野,為學習分散式相關知識打下基礎。

在閱讀本書之前,讀者需要具備以下基礎。

  • 具有一定的 Linux 作業系統基本操作的基礎知識。
  • 對於分散式系統的基礎有所瞭解,這關係到對叢集的理解。
  • 如果希望閱讀本書第3章至第7章關於 Kafka 基本元件實現原理及程式設計實戰的內容,需要具有 Java 或 Scala 語言基礎,尤其是 Java 語言基礎,這有助於閱讀 Kafka 原始碼和呼叫相應的 API。

參考資料

在寫作過程當中,我除閱讀了 Kafka 原始碼之外,還從網路上閱讀了大量參考資料,從中獲得了很多幫助,在此對這些前輩的無私奉獻精神表示由衷的欽佩和衷心的感謝。本書參考的資料如下。

讀者反饋

非常高興能將這本書分享給大家,也十分感謝大家購買和閱讀本書。在編寫本書時,雖然我精益求精,盡了最大的努力,但由於能力有限,加之時間倉促,書中難免存在不足甚至錯誤,敬請讀者給予指正。如果有任何問題和建議,讀者可傳送郵件至 moudaen@163.com。

致謝

在編寫本書時得到了很多人的幫助。

首先我要感謝我的妻子,在我編寫本書時你承擔了所有家務,讓我過著飯來張口、衣來伸手的生活,使我能夠全身心投入到寫作當中,這本書能夠完成有你一半的功勞。也要感謝我的家人,家永遠是我心靈的港灣,家人的愛永遠是我奮鬥的動力。同時也將本書獻給我即將出生的寶寶,願你健康成長,在未來的日子裡我會給你更多的驚喜。

然後我特別要感謝人民郵電出版社的楊海玲老師,感謝你一直以來給予我的支援和鼓勵,感謝你在本書編寫、出版整個過程當中的辛勤付出。也要感謝人民郵電出版社所有參與本書編輯和出版的老師們,正是由於你們的辛勤付出和一絲不苟的工作態度才讓本書出版成為可能。

同時要感謝我的工作單位海通證券,公司為我提供了一個非常優越的工作、學習和生活環境。在此要特別感謝部門領導和同事在我編寫本書過程中提出很多寶貴的建議,我很榮幸能夠與大家成為同事,共同奮鬥。

最後我要感謝所有培養過我的老師們,是你們教會了我用知識改變命運,用學習成就未來。

牟大恩

2017年9月於上海

第01章:Kafka 簡介

Kafka 是一個高吞吐量、分散式的釋出—訂閱訊息系統。據 Kafka 官方網站介紹,當前的 Kafka 已經定位為一個分散式流式處理平臺(a distributed streaming platform),它最初由 LinkedIn 公司開發,後來成為 Apache 專案的一部分。Kafka 核心模組使用 Scala 語言開發,支援多語言(如 Java、C/C++、Python、Go、Erlang、Node.js 等)客戶端,它以可水平擴充套件和具有高吞吐量等特性而被廣泛使用。目前越來越多的開源分散式處理系統(如 Flume、Apache Storm、Spark、Flink 等)支援與 Kafka 整合,本書第8章至第10章將通過具體案例詳細介紹 Kafka 與當前一些流行的分散式處理系統的整合應用。接下來我們將對 Kafka 相關知識做進一步深入介紹。

1.1 Kafka 背景

隨著資訊科技的快速發展及網際網路使用者規模的急劇增長,計算機所儲存的資訊量正呈爆炸式增長,目前資料量已進入大規模和超大規模的海量資料時代,如何高效地儲存、分析、處理和挖掘海量資料已成為技術研究領域的熱點和難點問題。當前出現的雲端儲存、分散式儲存系統、NoSQL 資料庫及列儲存等前沿技術在海量資料的驅使下,正日新月異地向前發展,採用這些技術來處理大資料成為一種發展趨勢。而如何採集和運營管理、分析這些資料也是大資料處理中一個至關重要的組成環節,這就需要相應的基礎設施對其提供支援。針對這個需求,當前業界已有很多開源的訊息系統應運而生,本書介紹的 Kafka 就是當前流行的一款非常優秀的訊息系統。

Kafka 是一款開源的、輕量級的、分散式、可分割槽和具有複製備份的(Replicated)、基於 ZooKeeper 協調管理的分散式流平臺的功能強大的訊息系統。與傳統的訊息系統相比,Kafka 能夠很好地處理活躍的流資料,使得資料在各個子系統中高效能、低延遲地不停流轉。

據 Kafka 官方網站介紹,Kafka 定位就是一個分散式流處理平臺。在官方看來,作為一個流式處理平臺,必須具備以下3個關鍵特性。

  • 能夠允許釋出和訂閱流資料。從這個角度來講,平臺更像一個訊息佇列或者企業級的訊息系統。
  • 儲存流資料時提供相應的容錯機制。
  • 當流資料到達時能夠被及時處理。

Kafka 能夠很好滿足以上3個特性,通過 Kafka 能夠很好地建立實時流式資料通道,由該通道可靠地獲取系統或應用程式的資料,也可以通過 Kafka 方便地構建實時流資料應用來轉換或是對流式資料進行響應處理。特別是在0.10版本之後,Kafka 推出了 Kafka Streams,這讓 Kafka 對流資料處理變得更加方便。

Kafka 已釋出多個版本。截止到編寫本書時,Kafka 的最新版本為0.10.1.1,因此本書內容都是基於該版本進行講解。

1.2 Kafka 基本結構

通過前面對 Kafka 背景知識的簡短介紹,我們對 Kafka 是什麼有了初步的瞭解,本節我們將進一步介紹 Kafka 作為訊息系統的基本結構。我們知道,作為一個訊息系統,其基本結構中至少要有產生訊息的元件(訊息生產者,Producer)以及消費訊息的元件(消費者,Consumer)。雖然消費者並不是必需的,但離開了消費者構建一個訊息系統終究是毫無意義的。Kafka訊息系統最基本的體系結構如圖1-1所示。

cbcf6e80-eaec-11e7-b678-1b1df9191e6d

圖1-1 Kafka 訊息系統最基本的體系結構

生產者負責生產訊息,將訊息寫入 Kafka 叢集;消費者從 Kafka 叢集中拉取訊息。至於生產者如何將生產的訊息寫入 Kafka,消費者如何從 Kafka 叢集消費訊息,Kafka 如何儲存訊息,Kafka 叢集如何管理排程,如何進行訊息負載均衡,以及各元件間如何進行通訊等諸多問題,我們將在後續章節進行詳細闡述,在本節我們只需對 Kafka 基本結構輪廓有個清晰認識即可。隨著對 Kafka 相關知識的深入學習,我們將逐步對 Kafka 的結構圖進行完善。

1.3 Kafka 基本概念

在對Kafka基本體系結構有了一定了解後,本節我們對Kafka的基本概念進行詳細闡述。

1.主題

Kafka 將一組訊息抽象歸納為一個主題(Topic),也就是說,一個主題就是對訊息的一個分類。生產者將訊息傳送到特定主題,消費者訂閱主題或主題的某些分割槽進行消費。

2.訊息

訊息是 Kafka 通訊的基本單位,由一個固定長度的訊息頭和一個可變長度的訊息體構成。在老版本中,每一條訊息稱為 Message;在由 Java 重新實現的客戶端中,每一條訊息稱為 Record。

3.分割槽和副本

Kafka 將一組訊息歸納為一個主題,而每個主題又被分成一個或多個分割槽(Partition)。每個分割槽由一系列有序、不可變的訊息組成,是一個有序佇列。

每個分割槽在物理上對應為一個資料夾,分割槽的命名規則為主題名稱後接“—”連線符,之後再接分割槽編號,分割槽編號從0開始,編號最大值為分割槽的總數減1。每個分割槽又有一至多個副本(Replica),分割槽的副本分佈在叢集的不同代理上,以提高可用性。從儲存角度上分析,分割槽的每個副本在邏輯上抽象為一個日誌(Log)物件,即分割槽的副本與日誌物件是一一對應的。每個主題對應的分割槽數可以在 Kafka 啟動時所載入的配置檔案中配置,也可以在建立主題時指定。當然,客戶端還可以在主題建立後修改主題的分割槽數。

分割槽使得 Kafka 在併發處理上變得更加容易,理論上來說,分割槽數越多吞吐量越高,但這要根據叢集實際環境及業務場景而定。同時,分割槽也是Kafka保證訊息被順序消費以及對訊息進行負載均衡的基礎。

Kafka 只能保證一個分割槽之內訊息的有序性,並不能保證跨分割槽訊息的有序性。每條訊息被追加到相應的分割槽中,是順序寫磁碟,因此效率非常高,這是 Kafka 高吞吐率的一個重要保證。同時與傳統訊息系統不同的是,Kafka 並不會立即刪除已被消費的訊息,由於磁碟的限制訊息也不會一直被儲存(事實上這也是沒有必要的),因此 Kafka 提供兩種刪除老資料的策略,一是基於訊息已儲存的時間長度,二是基於分割槽的大小。這兩種策略都能通過配置檔案進行配置,在這裡不展開探討,在3.5.4節將詳細介紹。

4.Leader 副本和 Follower 副本

由於 Kafka 副本的存在,就需要保證一個分割槽的多個副本之間資料的一致性,Kafka 會選擇該分割槽的一個副本作為 Leader 副本,而該分割槽其他副本即為 Follower 副本,只有 Leader 副本才負責處理客戶端讀/寫請求,Follower 副本從 Leader 副本同步資料。如果沒有 Leader 副本,那就需要所有的副本都同時負責讀/寫請求處理,同時還得保證這些副本之間資料的一致性,假設有n個副本則需要有n×n條通路來同步資料,這樣資料的一致性和有序性就很難保證。

引入 Leader 副本後客戶端只需與 Leader 副本進行互動,這樣資料一致性及順序性就有了保證。Follower 副本從 Leader 副本同步訊息,對於n個副本只需n−1條通路即可,這樣就使得系統更加簡單而高效。副本 Follower 與 Leader 的角色並不是固定不變的,如果 Leader 失效,通過相應的選舉演算法將從其他 Follower 副本中選出新的 Leader 副本。

5.偏移量

任何釋出到分割槽的訊息會被直接追加到日誌檔案(分割槽目錄下以“.log”為檔名字尾的資料檔案)的尾部,而每條訊息在日誌檔案中的位置都會對應一個按序遞增的偏移量。偏移量是一個分割槽下嚴格有序的邏輯值,它並不表示訊息在磁碟上的物理位置。由於Kafka幾乎不允許對訊息進行隨機讀寫,因此 Kafka 並沒有提供額外索引機制到儲存偏移量,也就是說並不會給偏移量再提供索引。消費者可以通過控制訊息偏移量來對訊息進行消費,如消費者可以指定消費的起始偏移量。為了保證訊息被順序消費,消費者已消費的訊息對應的偏移量也需要儲存。需要說明的是,消費者對訊息偏移量的操作並不會影響訊息本身的偏移量。舊版消費者將消費偏移量儲存到 ZooKeeper 當中,而新版消費者是將消費偏移量儲存到 Kafka 內部一個主題當中。當然,消費者也可以自己在外部系統儲存消費偏移量,而無需儲存到 Kafka 中。

6.日誌段

一個日誌又被劃分為多個日誌段(LogSegment),日誌段是 Kafka 日誌物件分片的最小單位。與日誌物件一樣,日誌段也是一個邏輯概念,一個日誌段對應磁碟上一個具體日誌檔案和兩個索引檔案。日誌檔案是以“.log”為檔名字尾的資料檔案,用於儲存訊息實際資料。兩個索引檔案分別以“.index”和“.timeindex”作為檔名字尾,分別表示訊息偏移量索引檔案和訊息時間戳索引檔案。

7.代理

在 Kafka 基本體系結構中我們提到了 Kafka 叢集。Kafka 叢集就是由一個或多個 Kafka 例項構成,我們將每一個 Kafka 例項稱為代理(Broker),通常也稱代理為 Kafka 伺服器(KafkaServer)。在生產環境中 Kafka 叢集一般包括一臺或多臺伺服器,我們可以在一臺伺服器上配置一個或多個代理。每一個代理都有唯一的標識 id,這個 id 是一個非負整數。在一個 Kafka 叢集中,每增加一個代理就需要為這個代理配置一個與該叢集中其他代理不同的 id,id 值可以選擇任意非負整數即可,只要保證它在整個 Kafka 叢集中唯一,這個 id 就是代理的名字,也就是在啟動代理時配置的 broker.id 對應的值,因此在本書中有時我們也稱為 brokerId。由於給每個代理分配了不同的 brokerId,這樣對代理進行遷移就變得更方便,從而對消費者來說是透明的,不會影響消費者對訊息的消費。代理有很多個引數配置,由於在本節只是對其概念進行闡述,因此不做深入展開,對於代理相關配置將穿插在本書具體元件實現原理、流程分析及相關實戰操作章節進行介紹。

8.生產者

生產者(Producer)負責將訊息傳送給代理,也就是向 Kafka 代理髮送訊息的客戶端。

9.消費者和消費組

消費者(Comsumer)以拉取(pull)方式拉取資料,它是消費的客戶端。在 Kafka 中每一個消費者都屬於一個特定消費組(ConsumerGroup),我們可以為每個消費者指定一個消費組,以 groupId 代表消費組名稱,通過 group.id 配置設定。如果不指定消費組,則該消費者屬於預設消費組 test-consumer-group。同時,每個消費者也有一個全域性唯一的 id,通過配置項 client.id 指定,如果客戶端沒有指定消費者的 id,Kafka 會自動為該消費者生成一個全域性唯一的 id,格式為 ${groupId}-${hostName}-${timestamp}-${UUID前8位字元}。同一個主題的一條訊息只能被同一個消費組下某一個消費者消費,但不同消費組的消費者可同時消費該訊息。消費組是 Kafka 用來實現對一個主題訊息進行廣播和單播的手段,實現訊息廣播只需指定各消費者均屬於不同的消費組,訊息單播則只需讓各消費者屬於同一個消費組。

10.ISR

Kafka 在 ZooKeeper 中動態維護了一個 ISR(In-sync Replica),即儲存同步的副本列表,該列表中儲存的是與 Leader 副本保持訊息同步的所有副本對應的代理節點 id。如果一個 Follower 副本當機(本書用當機來特指某個代理失效的情景,包括但不限於代理被關閉,如代理被人為關閉或是發生物理故障、心跳檢測過期、網路延遲、程式崩潰等)或是落後太多,則該 Follower 副本節點將從ISR列表中移除。

11.ZooKeeper

這裡我們並不打算介紹 ZooKeeper 的相關知識,只是簡要介紹 ZooKeeper 在 Kafka 中的作用。Kafka 利用 ZooKeeper 儲存相應後設資料資訊,Kafka 後設資料資訊包括如代理節點資訊、Kafka 叢集資訊、舊版消費者資訊及其消費偏移量資訊、主題資訊、分割槽狀態資訊、分割槽副本分配方案資訊、動態配置資訊等。Kafka 在啟動或執行過程當中會在 ZooKeeper 上建立相應節點來儲存後設資料資訊,Kafka 通過監聽機制在這些節點註冊相應監聽器來監聽節點後設資料的變化,從而由 ZooKeeper 負責管理維護 Kafka 叢集,同時通過 ZooKeeper 我們能夠很方便地對 Kafka 叢集進行水平擴充套件及資料遷移。

通過以上 Kafka 基本概念的介紹,我們可以對 Kafka 基本結構圖進行完善,如圖1-2所示。

enter image description here

圖1-2 Kafka 的叢集結構

1.4 Kafka 設計概述

1.4.1 Kafka 設計動機

Kafka 的設計初衷是使 Kafka 能夠成為統一、實時處理大規模資料的平臺。為了達到這個目標,Kafka 必須支援以下幾個應用場景。

(1)具有高吞吐量來支援諸如實時的日誌集這樣的大規模事件流。

(2)能夠很好地處理大量積壓的資料,以便能夠週期性地載入離線資料進行處理。

(3)能夠低延遲地處理傳統訊息應用場景。

(4)能夠支援分割槽、分散式,實時地處理訊息,同時具有容錯保障機制。

滿足以上功能的 Kafka 與傳統的訊息系統相比更像是一個資料庫日誌系統。瞭解了 Kafka 的設計動機之後,在下一節我們將看看 Kafka 發展至今已具有哪些特性。

1.4.2 Kafka 特性

上一節對 Kafka 的設計動機進行了介紹。隨著 Kafka 的不斷更新發展,當前版本的 Kafka 又增加了一些新特性,下面就來逐個介紹 Kafka 的這些新特性。

1.訊息持久化

Kafka 高度依賴於檔案系統來儲存和快取訊息。說到檔案系統,大家普遍認為磁碟讀寫慢,依賴於檔案系統進行儲存和快取訊息勢必在效能上會大打折扣,其實檔案系統儲存速度快慢一定程度上也取決於我們對磁碟的用法。據 Kafka 官方網站介紹:6塊7200r/min SATA RAID-5 陣列的磁碟線性寫的速度為600 MB/s,而隨機寫的速度為100KB/s,線性寫的速度約是隨機寫的6000多倍。由此看來磁碟的快慢取決於我們是如何去應用磁碟。加之現代的作業系統提供了預讀(read-ahead)和延遲寫(write-behind)技術,使得磁碟的寫速度並不是大家想象的那麼慢。同時,由於 Kafka 是基於 JVM(Java Virtual Machine)的,而 Java 物件記憶體消耗非常高,且隨著 Java 物件的增加 JVM 的垃圾回收也越來越頻繁和繁瑣,這些都加大了記憶體的消耗。鑑於以上因素,使用檔案系統和依賴於頁快取(page cache)的儲存比維護一個記憶體的儲存或是應用其他結構來儲存訊息更有優勢,因此 Kafka 選擇以檔案系統來儲存資料。

訊息系統資料持久化一般採用為每個消費者佇列提供一個 B 樹或其他通用的隨機訪問資料結構來維護訊息的後設資料,B樹操作的時間複雜度為O(log n),O(log n)的時間複雜度可以看成是一個常量時間,而且B樹可以支援各種各樣的事務性和非事務性語義訊息的傳遞。儘管B樹具有這些優點,但這並不適合磁碟操作。目前的磁碟尋道時間一般在10ms以內,對一塊磁碟來說,在同一時刻只能有一個磁頭來讀寫磁碟,這樣在併發IO能力上就有問題。同時,對樹結構效能的觀察結果表明:其效能會隨著資料的增長而線性下降。鑑於訊息系統本身的作用考慮,資料的持久化佇列可以建立在簡單地對檔案進行追加的實現方案上。因為是順序追加,所以Kafka在設計上是採用時間複雜度O(1)的磁碟結構,它提供了常量時間的效能,即使是儲存海量的資訊(TB 級)也如此,效能和資料的大小關係也不大,同時 Kafka 將資料持久化到磁碟上,這樣只要磁碟空間足夠大資料就可以一直追加,而不會像一般的訊息系統在訊息被消費後就刪除掉,Kafka 提供了相關配置讓使用者自己決定訊息要儲存多久,這樣為消費者提供了更靈活的處理方式,因此 Kafka 能夠在沒有效能損失的情況下提供一般訊息系統不具備的特性。

正是由於 Kafka 將訊息進行持久化,使得 Kafka 在機器重啟後,已儲存的訊息可繼續恢復使用。同時 Kafka 能夠很好地支援線上或離線處理、與其他儲存及流處理框架的整合。

2.高吞吐量

高吞吐量是 Kafka 設計的主要目標,Kafka 將資料寫到磁碟,充分利用磁碟的順序讀寫。同時,Kafka 在資料寫入及資料同步採用了零拷貝(zero-copy)技術,採用 sendFile() 函式呼叫,sendFile() 函式是在兩個檔案描述符之間直接傳遞資料,完全在核心中操作,從而避免了核心緩衝區與使用者緩衝區之間資料的拷貝,操作效率極高。Kafka 還支援資料壓縮及批量傳送,同時 Kafka 將每個主題劃分為多個分割槽,這一系列的優化及實現方法使得 Kafka 具有很高的吞吐量。經大多數公司對 Kafka 應用的驗證,Kafka 支援每秒數百萬級別的訊息。

3.擴充套件性

Kafka 要支援對大規模資料的處理,就必須能夠對叢集進行擴充套件,分散式必須是其特性之一,這樣就可以將多臺廉價的 PC 伺服器搭建成一個大規模的訊息系統。Kafka 依賴 ZooKeeper 來對叢集進行協調管理,這樣使得 Kafka 更加容易進行水平擴充套件,生產者、消費者和代理都為分散式,可配置多個。同時在機器擴充套件時無需將整個叢集停機,叢集能夠自動感知,重新進行負責均衡及資料複製。

4.多客戶端支援

Kafka 核心模組用 Scala 語言開發,但 Kafka 支援不同語言開發生產者和消費者客戶端應用程式。0.8.2 之後的版本增加了 Java 版本的客戶端實現,0.10 之後的版本已廢棄 Scala 語言實現的 Producer 及 Consumer,預設使用 Java 版本的客戶端。Kafka 提供了多種開發語言的接入,如 Java、Scala、C、C++、Python、Go、Erlang、Ruby、Node.js 等,感興趣的讀者可以詳見這裡。同時,Kafka 支援多種聯結器(Connector)的接入,也提供了 Connector API 供開發者呼叫。Kafka 與當前主流的大資料框架都能很好地整合,如 Flume、Hadoop、HBase、Hive、Spark、Storm 等。

5.Kafka Streams

Kafka 在0.10之後版本中引入 Kafak Streams。Kafka Streams 是一個用 Java 語言實現的用於流處理的 jar 檔案,關於 Kafka Streams 的相關內容將在第7章中進行講解。

6.安全機制

當前版本的 Kafka 支援以下幾種安全措施:

  • 通過 SSL 和 SASL(Kerberos),SASL/PLAIN 驗證機制支援生產者、消費者與代理連線時的身份認證;
  • 支援代理與 ZooKeeper 連線身份驗證;
  • 通訊時資料加密;
  • 客戶端讀、寫許可權認證;
  • Kafka 支援與外部其他認證授權服務的整合。
7.資料備份

Kafka 可以為每個主題指定副本數,對資料進行持久化備份,這可以一定程度上防止資料丟失,提高可用性。

8.輕量級

Kafka 的代理是無狀態的,即代理不記錄訊息是否被消費,消費偏移量的管理交由消費者自己或組協調器來維護。同時叢集本身幾乎不需要生產者和消費者的狀態資訊,這就使得 Kafka 非常輕量級,同時生產者和消費者客戶端實現也非常輕量級。

9.訊息壓縮

Kafka 支援 Gzip、Snappy、LZ4 這3種壓縮方式,通常把多條訊息放在一起組成 MessageSet,然後再把 MessageSet 放到一條訊息裡面去,從而提高壓縮比率進而提高吞吐量。

1.4.3 Kafka 應用場景

訊息系統或是說訊息佇列中介軟體是當前處理大資料一個非常重要的元件,用來解決應用解耦、非同步通訊、流量控制等問題,從而構建一個高效、靈活、訊息同步和非同步傳輸處理、儲存轉發、可伸縮和最終一致性的穩定系統。當前比較流行的訊息中介軟體有 Kafka、RocketMQ、RabbitMQ、ZeroMQ、ActiveMQ、MetaMQ、Redis 等,這些訊息中介軟體在效能及功能上各有所長。如何選擇一個訊息中介軟體取決於我們的業務場景、系統執行環境、開發及運維人員對訊息中件間掌握的情況等。我認為在下面這些場景中,Kafka 是一個不錯的選擇。

(1)訊息系統。Kafka 作為一款優秀的訊息系統,具有高吞吐量、內建的分割槽、備份冗餘分散式等特點,為大規模訊息處理提供了一種很好的解決方案。

(2)應用監控。利用 Kafka 採集應用程式和伺服器健康相關的指標,如 CPU 佔用率、IO、記憶體、連線數、TPS、QPS 等,然後將指標資訊進行處理,從而構建一個具有監控儀表盤、曲線圖等視覺化監控系統。例如,很多公司採用 Kafka 與 ELK(ElasticSearch、Logstash 和 Kibana)整合構建應用服務監控系統。

(3)網站使用者行為追蹤。為了更好地瞭解使用者行為、操作習慣,改善使用者體驗,進而對產品升級改進,將使用者操作軌跡、內容等資訊傳送到 Kafka 叢集上,通過 Hadoop、Spark 或 Strom 等進行資料分析處理,生成相應的統計報告,為推薦系統推薦物件建模提供資料來源,進而為每個使用者進行個性化推薦。

(4)流處理。需要將已收集的流資料提供給其他流式計算框架進行處理,用 Kafka 收集流資料是一個不錯的選擇,而且當前版本的 Kafka 提供了 Kafka Streams 支援對流資料的處理。

(5)永續性日誌。Kafka 可以為外部系統提供一種永續性日誌的分散式系統。日誌可以在多個節點間進行備份,Kafka 為故障節點資料恢復提供了一種重新同步的機制。同時,Kafka 很方便與 HDFS 和 Flume 進行整合,這樣就方便將 Kafka 採集的資料持久化到其他外部系統。

1.5 本書導讀

本書在結構編排上,先介紹 Kafka 基礎知識,接著介紹 Kafka 應用環境搭建,然後對 Kafka 核心元件實現原理進行簡要講解。在核心元件原理講解之後,又將相應元件應用串起來分析 Kafka 核心流程,之後從 Kafka 基本指令碼操作實戰開始,結合 Kafka 在實際工作中應用案例詳細介紹 Kafka 與當前主流大資料處理框架的應用。同時,將 Kafka Streams 獨立成一章進行詳細介紹,基本上覆蓋了 Kafka Streams 的核心及重要知識的講解。

為了編寫和講解方便,本書有以下幾點約定說明。

(1)本書所講 Kafka 版本為 0.10.1.1,書中提及的當前版本 Kafka 均指這一版本。

(2)在 Kafka 基本元件實現原理講解時,為了指明方法所屬的物件,本書簡單地以“類名.方法名()”的形式說明,這並不表示對類靜態方法的呼叫。同時,鑑於篇幅考慮也省去了方法引數列表,但不代表該方法無引數。

(3)讀者在閱讀本書時經常會看到“${屬性欄位}”表示式,本書以此表示該屬性欄位對應的值。

1.6 小結

本章首先對 Kafka 背景及一個簡單的 Kafka 訊息系統基本結構進行了簡單介紹,然後對 Kafka 涉及的基本概念進行了闡述,最後就 Kafka 的設計思想、特性及應用場景進行了歸納。

第02章:Kafka 安裝配置(上)

本章將詳細介紹 Kafka 執行環境的搭建,包括在 Linux 系統和 Windows 系統中搭建 Kafka 執行環境。

2.1 基礎環境配置

由於 Kafka 是用 Scala 語言開發的,執行在 JVM 上,因此在安裝 Kafka 之前需要先安裝 JDK。

2.1.1 JDK 安裝配置

最新版本的 Kafka 需要執行在 JDK 1.7 以上,Kafka 官方網站推薦使用 JDK 1.8,因此本書所應用的 JDK 環境採用 JDK 1.8。下面將詳細介紹 JDK 1.8 安裝步驟。

1.Windows 安裝 JDK

(1)下載並安裝。首先在 Oracle 官方網站 下載 JDK 1.8 安裝檔案,根據作業系統型別選擇相應的 JDK 版本。我使用的是64位作業系統,因此下載 jdk-8u111-windows-x64.exe 安裝檔案。下載完成後,雙擊執行安裝。在安裝時可以選擇安裝路徑,這裡在安裝時全使用預設路徑。

(2)環境變數配置。在系統變數中新增變數名 JAVA_HOME,變數值為 JDK 1.8 安裝路徑。由於 Java 預設安裝在 Program Files 目錄下,這個目錄名之間有空格,有可能在執行某些應用時因 JDK 安裝路徑有空格而報錯。例如,我在安裝 JDK 後,執行 Kafka 時報如下錯誤:

錯誤: 找不到或無法載入主類 Files\Java\jdk1.8.0_111\lib\dt.jar;C:\Program

為了避免出現類似的錯誤,在 Windows 系統上,若 JDK 安裝在 Program File 目錄下,在設定JAVA_HOME時,用該目錄別名 PROGRA~1,因此將JAVA_HOME設定為 C:\PROGRA~1\Java\jdk1.8.0_111。新增變數名 CLASSPATH,變數值為 .;% JAVA_HOME%\lib\dt.jar;% JAVA_HOME%\ lib\tools.jar。本步操作 JDK 環境變數配置如表2-1所示。

表2-1 JDK 環境變數配置

變 量 類 型變 量 名變 量 值
系統變數JAVA_HOMEC:\PROGRA~1\Java\jdk1.8.0_111
使用者變數CLASSPATH.;% JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar

(3)驗證。環境變數配置完成後,在 Windows 的 cmd 終端輸入檢視 Java 版本的命令,以此來驗證 JDK 安裝配置是否成功。命令如下:

Java –version

若輸出為以下 JDK 版本資訊,則表示 JDK 1.8 已安裝成功,且為系統預設 JDK。

Java version "1.8.0_111"Java(TM) SE Runtime Environment (build 1.8.0_111-b14)Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
2.Linux 安裝 JDK

一些 Linux 的發行版預設已安裝了 JDK,如 OpenJDK,這裡所用的 Linux 作業系統預設已經安裝了 OpenJDK。輸入下面的命令檢視JDK版本資訊:

Java  –version

輸出 JDK 版本資訊如下:

Java version "1.7.0_45"OpenJDK Runtime Environment (rhel-2.4.3.3.el6-x86_64 u45-b15)OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)

然而有些 Linux 系統並沒有安裝 JDK,因此本小節將詳細講解如何在 Linux 中安裝 JDK。這裡我們講解 JDK 1.8 的安裝。

(1)下載並安裝。進入 Oracle 官方網站 下載 Linux 版本的 JDK 1.8 安裝包。這裡我們下載的安裝包版本為 jdk-8u111-linux-x64.gz,並將安裝包解壓到 /usr/local/software/Java 路徑下。

tar -xzvf jdk-8u111-linux-x64.gz      # 解壓jdk安裝包

將安裝包解壓後,即完成 JDK 的安裝。

(2)配置環境變數。在 /etc/profile 檔案中新增 JDK 和 JRE 的路徑,並新增到 Path 中,操作命令如下:

vi /etc/profile      # 編輯profile檔案

在檔案中新增以下內容:

export JAVA_HOME=/usr/local/software/Java/jdk1.8.0_111export JRE_HOME=/usr/local/software/Java/jdk1.8.0_111/jreexport PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin

儲存退出。若系統預設安裝了 OpenJDK,則使用者可以選擇將其刪除,也可以修改配置用最新安裝的版本替換 OpenJDK。這裡選擇用新安裝的 JDK 替換系統自帶的 OpenJDK,則按序執行以下命令。

  • 將 Java 新增到 bin:
    update-alternatives --install /usr/bin/Java Java /usr/local/software/Java/jdk1.8.0_111 300
  • 將 Javac 新增到 bin:
    update-alternatives --install /usr/bin/Javac Javac /usr/local/software/            Java/jdk1.8.0_111/bin/Javac 300
  • 選擇 JDK 版本:
    update-alternatives --config Java

執行以上命令會出現 JDK 版本選擇介面,如圖2-1所示。這裡我們選擇新安裝的 JDK 1.8,即輸入序號3,按Enter鍵。

enter image description here

圖2-1 Linux 控制檯展示的 JDK 版本選擇命令列介面

環境變數配置好後執行以下命令,讓剛才的修改操作立即生效:

    source /etc/profile           # 讓對/etc/profile的修改立即生效 

(3)驗證。輸入檢視 JDK 版本命令,檢視環境變數配置是否成功,執行以下命令:

Java –version      # 檢視jdk版本 

輸出以下 JDK 版本資訊:

Java version "1.8.0_111"Java(TM) SE Runtime Environment (build 1.8.0_111-b14)Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)

由以上 JDK 版本資訊可知,JDK 版本已替換為新安裝的 JDK 1.8版本。至此,JDK 安裝完成。

2.1.2 SSH 安裝配置

對 Kafka 叢集本身來講,配置 SSH 免金鑰登入並不是必需的步驟,但作為分散式系統,一般會由多臺機器構成。為了便於操作管理,如通過 SSH 方式啟動叢集代理等,這裡對 SSH 安裝配置進行介紹。

(1)在根目錄下檢視是否存在一個隱藏資料夾.ssh。若沒有該資料夾,則在確保機器聯網條件下執行以下命令安裝 ssh:

sudo apt-get install ssh      # 安裝ssh 

(2)進入.ssh 目錄,生成金鑰對,執行命令如下:

ssh-keygen -t rsa      # 產生金鑰 

在執行以上命令時一路回車即可。ssh-keygen 用於生成認證金鑰,-t 用來指定金鑰型別,這裡選擇 rsa 金鑰。執行完畢後會在 ~/.ssh 目錄下生成 id_rsaid_rsa.pub兩個檔案,其中id_rsa為私鑰檔案,id_rsa.pub 為公鑰檔案。依次在叢集其他機器上完成步驟1和步驟2。

(3)將 id_rsa.pub 檔案內容追加到授權的 key 檔案中,命令如下:

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys      # 追加公鑰到授權檔案中

若是單機環境,則至此已完成 ssh 配置。

(4)將第一臺機器的 authorized_keys檔案複製到第二臺機器上,並將第二臺機器的公鑰也追加到 authorized_keys 檔案中,依次執行以下命令:

scp authorized_keys root@172.117.12.62:~/.ssh/   # 複製第一臺機器的授權檔案到第二臺機器cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys  # 在第二臺機器上執行此命令,將第二臺機器的公鑰追加到授權檔案中

(5)將第二臺機器的authorized_keys檔案複製到第三臺機器上,並將第三臺機器的公鑰追加到 authorized_keys 檔案中,執行命令如下:

scp authorized_keys root@172.117.12.63:~/.ssh/   # 複製第二臺機器的授權檔案到第三臺機器cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys   # 在第三臺機器上執行此命令,將第三臺機器的公鑰追加到授權檔案中

若叢集還有更多機器,則依此類推完成授權檔案合併。至此 ssh 配置完成,在已配置 ssh 的任何一臺機器上均可免密登入到其他機器。例如,在第一臺機器上執行以下 ssh 命令,輸出如下(首次登入會讓輸入密碼):

[root@rhel65 .ssh]# ssh 172.117.12.61The authenticity of host '172.117.12.61 (172.117.12.61)' can't be established.RSA key fingerprint is a3:5b:a9:29:ed:00:74:f4:ce:51:e5:7c:42:5b:8d:44.Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added '172.117.12.61' (RSA) to the list of known hosts.root@172.117.12.61's password: Last login: Wed Feb  8 17:30:11 2017 from server-1[root@rhel65 ~]# ssh 172.117.12.61Last login: Wed Feb  8 17:32:04 2017 from server-3[root@rhel65 ~]# ssh 172.117.12.62Last login: Wed Feb  8 17:26:09 2017 from server-1

2.1.3 ZooKeeper 環境

ZooKeeper 是一個分散式應用程式協調服務框架,分散式應用程式可以基於 ZooKeeper 來實現同步服務、配置維護、命名服務等,ZooKeeper 能提供基於類似於檔案系統的目錄節點樹方式的資料儲存,通過監控各節點資料狀態的變化,達到基於資料的叢集管理。ZooKeeper 主要由表2-2所示的幾個角色構成。

表2-2 ZooKeeper 叢集主要角色說明

角  色描  述
Leader叢集的領導者,負責投票的發起和決議及更新系統狀態
LearnerFollower跟隨者,接受客戶端的請求並返回結果給客戶端,參與投票
Observer接受客戶端的請求,將寫的請求轉發給 Leader,不參與投票。Observer 目的是擴充套件系統,提高讀的速度

關於 ZooKeeper 的原理及其他相關知識,讀者可查閱 ZooKeeper 官方網站及相關書籍進行深入瞭解。

Kafka 依賴 ZooKeeper,通過 ZooKeeper 來對代理、消費者上下線管理、叢集、分割槽後設資料管理等,因此 ZooKeeper 也是 Kafka 得以執行的基礎環境之一。

進入 ZooKeeper 官方網站下載 ZooKeeper(本書所用 ZooKeeper 版本為 zookeeper-3.4.8),然後將下載檔案解壓到指定目錄。對 ZooKeeper 的安裝,下面按 Windows 和 Linux 分別進行講解。

1.Windows 安裝 ZooKeeper

一般會選擇在 Linux 作業系統上安裝和部署分散式服務,因此這裡並不打算講解 Windows 環境下 ZooKeeper 叢集環境搭建,只是簡單介紹 Windows 環境下 ZooKeeper 單機模式的安裝。

(1)解壓安裝。首先將 ZooKeeper 安裝包 zookeeper-3.4.8.tar.gz 解壓到相應目錄,這裡將 ZooKeeper 解壓到 D:\software\zookeeper-3.4.8 目錄下。然後進入 ZooKeeper 安裝路徑 conf 目錄下,會看到 ZooKeeper 提供了一個 zoo_sample.cfg 的配置模板,將該檔案重新命名為 zoo.cfg。zoo.cfg 檔案中只需修改 dataDir 和 dataLogDir 配置,其他配置使用預設值(其他配置及其含義將在下面的“Linux 搭建 ZooKeeper 環境”小節詳細介紹)。這裡對 dataDir 和 dataLogDir 配置如下:

dataDir=F:\\zookeeper\\datadataLogDir=F:\\zookeeper\\logs

至此,Windows 環境下 ZooKeeper 安裝配置完成。下面進入 ZooKeeper 安裝路徑 bin 目錄下,啟動及驗證 ZooKeeper 安裝是否成功。

(2)驗證。執行啟動 ZooKeeper 命令:

zkServer.cmd    # windows下啟動ZooKeeper 

若輸出沒有任何錯誤,通過 jps 命令可以看到 ZooKeeper 相關程式。輸入命令:

jps  # 檢視Java程式命令

輸出結果中至少包括以下程式名:

12008 QuorumPeerMain11596 Jps

還可以進入 ZooKeeper 的安裝路徑 bin 目錄下,通過 ZooKeeper 客戶端連線到 ZooKeeper 服務,執行以下命令進一步驗證 ZooKeeper 是否安裝成功:

zkCli.cmd -server 127.0.0.1:2181   # 登入到ZooKeeper伺服器 

在輸出資訊中會看到“Welcome to ZooKeeper!”,同時顯示接受命令輸入介面。

在客戶端輸入:

ls /      # 檢視 ZooKeeper 伺服器目錄結構 

此時 ZooKeeper 伺服器中僅有一個 zookeeper 節點,資訊顯示如下:

[zk: 127.0.0.1:2181(CONNECTED) 0] ls /[zookeeper]

至此,Windows 環境下安裝 ZooKeeper 講解完畢。

2.Linux 搭建 ZooKeeper 環境

在 Linux 環境下 ZooKeeper 單機模式配置與上一小節介紹的 Windows 環境下 ZooKeeper 安裝配置的操作步驟基本相同,因此本小節直接介紹 ZooKeeper 分散式環境搭建。下面將講解在 Linux 環境下如何配置由3臺機器構成的 ZooKeeper 叢集環境,這3臺機器的 IP 地址分別為 172.117.12.61、172.117.12.62 和 172.117.12.63。

(1)解壓安裝。首先在3臺機器上分別將 zookeeper-3.4.8.tar.gz 解壓到 /usr/local/software/ zookeeper 目錄。進入解壓後的 zookeeper-3.4.8 /conf 目錄,將 zoo.sample.cfg 重新命名為 zoo.cfg。關於 ZooKeeper 配置檔案中幾個基礎配置項的說明如表2-3所示。

表2-3 ZooKeeper 基礎配置說明

配 置 項默 認 值說  明
tickTime2000msZooKeeper 中的一個時間單元。ZooKeeper 中所有時間都以這個時間單元為基準,進行整數倍配置,預設是2 s
initLimit10Follower 在啟動過程中,會從 Leader 同步所有最新資料,確定自己能夠對外服務的起始狀態。當 Follower 在 initLimt個tickTime 還沒有完成資料同步時,則 Leader 仍為 Follower 連線失敗
syncLimit5Leader 與 Follower 之間通訊請求和應答的時間長度。若 Leader 在 syncLimit 個 tickTime 還沒有收到 Follower 應答,則認為該 Leader 已下線
dataDir/tmp/zookeeper儲存快照檔案的目錄,預設情況下,事務日誌也會儲存在該目錄上。由於事務日誌的寫效能直接影響 ZooKeeper 效能,因此建議同時配置引數 dataLogDir
dataLogDir/tmp/zookeeper事務日誌輸出目錄
clientPort2181ZooKeeper 對外埠

請讀者根據自已伺服器環境,修改 zoo.cfg 檔案中表2-3提及引數的配置。這裡只修改了以下兩個配置項,其他幾個基礎配置沿用預設值。

dataDir=/opt/data/zookeeper/datadataLogDir=/opt/data/zookeeper/logs

若是單機模式,操作至此完成。接下來配置將3臺機器構成一個分散式叢集。

(2)叢集配置。首先在3臺機器的/etc/hosts檔案中加入3臺機器的 IP 與機器域名對映,域名自定義,這裡分別命名為 server-1、server-2、server-3,3臺機器 IP 與機器域名對映關係如下:

172.117.12.61 server-1172.117.12.62 server-2172.117.12.63 server-3

然後進入其中一臺機器的 ZooKeeper 安裝路徑 conf 目錄。這裡我們選擇在 IP 為 172.117.12.61 的機器上進行配置,編輯 conf/zoo.cfg 檔案,在該檔案中新增以下配置:

server.1=server-1:2888:3888server.2=server-2:2888:3888server.3=server-3:2888:3888

為了便於講解以上配置,在這裡抽象一個公式,即 server.n=n-server-domain:port1:port2。這個公式中的 n 是一個數字型別常量,這裡配置的1、2和3用於表示第幾臺 ZooKeeper 伺服器;n-server-domain 表示第 n 臺 ZooKeeper 伺服器的 IP 所對映的域名,當然這裡也可以是第 n 臺機器的 IP;port1 表示該伺服器與叢集中的 Leader 交換資訊的埠,預設是 2888;port2 表示選舉時伺服器相互通訊的埠。

接著在${dataDir}路徑下建立一個 myid 檔案。myid 裡存放的值就是伺服器的編號,即對應上述公式中的 n,在這裡第一臺機器 myid 存放的值為1。ZooKeeper 在啟動時會讀取 myid 檔案中的值與 zoo.cfg 檔案中的配置資訊進行比較,以確定是哪臺伺服器。

在 zoo.cfg 檔案中我們同時配置了3臺機器,因此接下來通過 scp 命令將本臺機器的 zoo.cfg 檔案複製到另外兩臺機器相應目錄進行替換。

scp zoo.cfg root@172.117.12.62:/usr/local/software/zookeeper/zookeeper-3.4.8/conf/scp zoo.cfg root@172.117.12.63:/usr/local/software/zookeeper/zookeeper-3.4.8/conf/

然後分別修改另外兩臺機器的 myid。同時,為了操作方便,我們將 ZooKeeper 相關環境變數新增到 /etc/profile 檔案當中。

設定 ZooKeeper 安裝路徑,在 /etc/profile 相關環境變數配置中新增以下資訊:

export ZOOKEEPER_HOME=/usr/local/software/zookeeper/zookeeper-3.4.8

在該檔案的 Path 配置項最後加上:$ZOOKEEPER_HOME/bin。注意,在$ZOOKEEPER_HOME前有一個冒號。然後執行 source/etc/profile 命令使所做的修改操作立即生效。其他兩臺機器也進行同樣的環境設定。至此,由3臺機器構成的分散式 ZooKeeper 環境搭建步驟介紹完畢。下面啟動 ZooKeeper 進行驗證。

(3)驗證。由於配置了 ZooKeeper 環境變數,因此無需進入 ZooKeeper 安裝路徑 bin 目錄下。在這3臺機器上分別啟動 ZooKeeper:

zkServer.sh start    # 啟動ZooKeeper服務

輸出如下資訊:

ZooKeeper JMX enabled by defaultUsing config: /usr/local/software/zookeeper/zookeeper-3.4.8/bin/../conf/zoo.cfgStarting zookeeper ... STARTED

檢視這3臺 ZooKeeper 伺服器狀態,依次在這3臺機器上執行以下命令:

zkServer.sh status    # 查詢zookeeper狀態 

執行上述啟動命令,其中有兩臺機器輸出以下資訊:

ZooKeeper JMX enabled by defaultUsing config: /usr/local/software/zookeeper/zookeeper-3.4.8/bin/../conf/zoo.cfgMode: follower

另外一臺機器輸出資訊如下:

ZooKeeper JMX enabled by defaultUsing config: /usr/local/software/zookeeper/zookeeper-3.4.8/bin/../conf/zoo.cfgMode: leader 

可以看到,這3臺機器中,一臺機器作為 Leader,其他兩臺伺服器作為 Follower。同時,可以檢視 zookeeper.out 檔案內容,通過啟動日誌進一步瞭解 ZooKeeper 執行過程。至此,ZooKeeper 叢集環境搭建講解完畢。

第02章:Kafka 安裝配置(中)

2.2 Kafka 單機環境部署

Kafka 安裝較簡單,不同作業系統下安裝步驟基本相同,針對大多數使用者來講,在生產環境使用 Kafka 一般選擇 Linux 伺服器,本書 Kafka 實戰操作也是基於 Linux 環境進行講解的。下面分別介紹 Kafka 在 Windows 作業系統以及 Linux 作業系統的安裝步驟,Mac 作業系統的安裝步驟與 Linux 作業系統的安裝步驟基本類似,不再介紹。同時,後面幾節中的 Kafka 叢集環境搭建也只介紹在 Linux 環境下 Kafka 叢集環境的部署。

2.2.1 Windows 環境安裝 Kafka

Windows 下安裝 Kafka 只需將下載的 Kafka 安裝包解壓到相應目錄即可。

(1)下載及安裝。進入 Kafka 官方網站下載當前最新版本的 Kafka,Kafka 安裝包並沒有區分 Windows 安裝包還是 Linux 安裝包,僅在 bin 目錄下將 Windows 環境執行 Kafka 的相關指令碼放在 /bin/windows 目錄下。當前 Kafka 最新版本為 kafka_2.11-0.10.1.1.tgz,其中 2.11 代表 Scala 版本,0.10.1.1 表示 Kafka 的版本。這裡將下載的安裝包解壓到 D:\software\kafka_2.11-0.10.1.1目錄下,為了便於講解,這裡記 Kafka 安裝路徑為$KAFKA_HOME。至此,Windows 下 Kafka 完成安裝。當然我們也可以像安裝 JDK 一樣配置 Kafka 環境變數,感興趣的讀者可以自行配置,這步操作不是必需的步驟,因此不再闡述。

(2)啟動 KafkaServer 驗證。安裝好 Kafka 後,啟動 KafkaServer。在啟動 Kafka 之前,需要啟動 Zoookeeper。若 ZooKeeper 服務不是本地服務,應修改 Kafka 安裝目錄下 /config/server.properties 檔案 zookeeper.connect 配置項,然後在 Windows 的 cmd 下進入$KAFKA_HOME/bin/windows目錄,執行以下命令,啟動 KafkaServer。

kafka-server-start.bat ../../config/server.properties   # windows下啟動kafak server

若在啟動過程中沒有報任何異常資訊,同時在控制檯最後輸出列印內容如圖2-2所示,則表示 Kafka 在 Windows 環境下安裝成功。

enter image description here

圖2-2 KafkaServer 啟動日誌

2.2.2 Linux 環境安裝 Kafka

在 Linux 系統上安裝 Kafka 與在 Windows 系統上安裝操作基本相同,將安裝包解壓到相應目錄,這裡依然將 Kafka 安裝目錄記為$KAFKA_HOME,修改$KAFKA_HOME/config/server.properties檔案相關配置即可。這裡安裝 Kafka 所用機器與安裝 ZooKeeper 的機器相同,但在生產環境,一般將 ZooKeeper 叢集與 Kafka 機器分機架部署。在講解 Kafka 單機版本安裝時,我們選擇3臺機器中的一臺,IP 為 172.117.12.61。

(1)解壓安裝。先將 Kafka 安裝包 kafka_2.11-0.10.1.1.tgz 解壓到指定目錄下,這裡將 Kafka 解壓到 /usr/local/software/kafka 目錄下。進入 /usr/local/software/kafka 目錄執行以下命令解壓 Kafka 安裝包。

tar -xzvf kafka_2.11-0.10.1.1.tgz      # 解壓安裝Kafka

由於後續對 Kafka 的講解都是在 Linux 環境下,因此為了操作方便我們對 Kafka 的環境變數進行設定。在 /etc/profile 檔案中加入 Kafka 安裝路徑,並將 Kafka 的 bin 目錄新增進 Path 中。這一步操作並非 Kafka 安裝必需的設定,讀者可根據情況選擇是否需要對 Kafka 環境變數進行配置。開啟 /etc/profile 檔案新增以下配置。

  • 指定 Kafka 安裝路徑:
    export KAFKA_HOME=/usr/local/software/kafka/kafka_2.11-0.10.1.1
  • 將 Kafka bin 目錄加到 Path。在 Path 設定後新增:$KAFKA_HOME/bin,新增 Kafka bin 後完整的 Path 如下:
    export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$KAFKA_HOME/bin

儲存檔案退出,執行 source /etc/profile 命令讓剛才新增的 Kafka 環境變數設定生效。再在任一路徑下輸入 kafka 然後按 Tab 鍵,會提示補全 Kafka 執行相關指令碼.sh 檔案,表示 Kafka 環境變數配置成功,但一般 Kafka 指令碼執行時會載入 /config 路徑下的相關配置檔案,因此當不在 Kafka 安裝目錄 bin 下執行相關指令碼時,需要指定配置檔案絕對路徑。

(2)修改配置。修改$KAFKA_HOME/config目錄下的 server.properties 檔案,為了便於後續叢集環境搭建的配置,需要保證同一個叢集下 broker.id 要唯一,因此這裡手動配置 broker.id,直接保持與 ZooKeeper 的 myid 值一致,同時配置日誌儲存路徑。server.properties 修改的配置如下:

broker.id=1                      # 指定代理的 idlog.dirs=/opt/data/kafka-logs    # 指定 Log 儲存路徑

其他配置保持不變,由於 172.117.12.61 這臺機器本地已安裝了 ZooKeeper,因此在 Kafka 單機版本安裝講解時,我們暫不對 zookeeper.connect 配置進行修改,其他配置檔案也暫不進行修改。

(3)驗證

  • 啟動 Kafka,要保證 ZooKeeper 已正常啟動,進入 Kafka 安裝路徑$KAFKA_HOME/ bin目錄下,執行啟動 KafkaServer 命令。
    kafka-server-start.sh -daemon ../config/server.properties    # 啟動Kafka

執行 jps 命令檢視 Java 程式,此時程式資訊至少包括以下幾項:

    15976 Jps    14999 QuorumPeerMain    15906 Kafka

可以看到 ZooKeeper 程式和 Kafka 程式名,同時進入$KAFKA_HOME/logs目錄下,檢視 server.log 會看到 KafkaServer 啟動日誌,在啟動日誌中會記錄 KafkaServer 啟動時載入的配置資訊。

  • 通過 ZooKeeper 客戶端登入 ZooKeeper 檢視目錄結構,執行以下命令:
    zkCli.sh -server server-1:2181    # 登入ZooKeeper     ls /                              # 檢視ZooKeeper目錄結構

在 Kafka 啟動之前 ZooKeeper 中只有一個 zookeeper 目錄節點,Kafka 啟動後目錄節點如下:

    [cluster, controller, controller_epoch, brokers, zookeeper, admin, isr_change_           notification, consumers, config]

執行以下命令,檢視當前已啟動的 Kafka 代理節點:

    ls /brokers/ids      # 檢視已啟動的代理節點     [1]                  # 已啟動的代理節點對應的 brokerId

輸出資訊顯示當前只有一個 Kafka 代理節點,當前代理的 brokerId 為1。至此,Kafka 單機版安裝配置介紹完畢,相關操作我們將在第5章進行詳細介紹。

2.3 Kafka 偽分散式環境部署

KafkaServer 啟動時需要載入一個用於 KafkaServer 初始化相關配置的 server.properties 檔案,當然檔名可以任意,一個 server.properties 對應一個 KafkaServer 例項。Kafka 偽分散式就是在一臺機器上啟動多個 KafkaServer 來達到多代理的效果,因此要保證 broker.id 及 port 在同一臺機器的多個 server.properities 中唯一。

本節在上一節的 Linux 安裝 Kafka 基礎配置之上,將 server.properties 檔案複製一份並命名為 server-0.properties,在 server-0.properties 檔案中修改配置如下:

broker.id=0log.dirs=/opt/data/kafka-logs/broker-0port=9093

由於代理預設埠是 9092,server.properties 沒有設定埠則採用預設設定,因此在 server-0.properties 將 port 設定為 9093。這個埠可以自定義,只要新埠沒有被佔用即可。執行以下命令,分別啟動 brokerId 為 0 和 1 的兩個 KafkaServer:

kafka-server-start.sh -daemon ../config/server-0.properties      # 啟動代理0kafka-server-start.sh -daemon ../config/server.properties        # 啟動代理1

再次執行 jps 命令檢視 Java 程式資訊,列印輸出如下資訊:

19453 Kafka18036 ZooKeeperMain18228 QuorumPeerMain19169 Kafka19504 Jps

從輸出的程式資訊可以看到有兩個 Kafka 程式存在,即代表剛才啟動的 broker.id 為 0 和 1 的兩個代理。此時登入 ZooKeeper 客戶端,再檢視 ZooKeeper 的 /brokers/ids 目錄,會看到該目錄下有兩個節點:

[zk: 172.117.12.61(CONNECTED) 0] ls /brokers/ids[0, 1]

這樣,一臺機器上啟動多個代理的偽分散式環境安裝配置介紹完畢。

2.4 Kafka 叢集環境部署

2.2.2節已經講解了 Kafka 單機版安裝配置,因此對 Kafka 叢集環境配置時只需將單機版安裝的 Kafka 配置進行相應修改,然後複製到另外兩臺機器即可。這裡只需修改 server.properties 檔案中 Kafka 連線 ZooKeeper 的配置,將 Kafka 連線到 ZooKeeper 叢集,配置格式為“ZooKeeper 伺服器 IP:ZooKeeper 的客戶端埠”,多個 ZooKeeper 機器之間以逗號分隔開。

zookeeper.connect=server-1:2181,server-2:2181,server-3:2181

進入 172.117.12.61 伺服器 /usr/local/software 目錄下,執行以下兩條命令將本機安裝的 Kafka 分別複製到另外兩臺伺服器上:

scp -r kafka_2.11-0.10.1.1  root@172.117.12.62:/usr/local/software/kafkascp -r kafka_2.11-0.10.1.1  root@172.117.12.63:/usr/local/software/kafka

複製完成後,分別登入另外兩臺機器,修改 server.properties 檔案中的 broker.id 依次為2和3。當然可以設定任一整數,只要保證一個叢集中 broker.id 唯一即可。同時在3臺機器的 server.properties 檔案中設定 host.name 為本機的 IP。例如,對主機名為 server-1 的機器上的 Kafka 節點,在 server.properties 檔案中增加 host.name=172.117.12.61。本書所用版本的 Kafka 若不設定 host.name,則會在建立主題及向主題傳送訊息時發生NOT_LEADER_FOR_PARTITION這樣的異常。

配置完畢後,分別啟動3臺機器的 KafkaServer,通過 ZooKeeper 客戶端檢視 Kafka 在 ZooKeeper 中的相應後設資料資訊,其中檢視 /brokers/ids 節點資訊如下:

[zk: 172.117.12.61(CONNECTED) 1] ls /brokers/ids[1, 2, 3]

由 /brokers/ids 節點儲存的後設資料可知,3臺機器的 Kafka 均已正常已啟動。至此,Kafka 分散式環境搭建過程介紹完畢。

2.5 Kafka Manager 安裝

在實際應用中,我們經常需要了解叢集的執行情況,如檢視叢集中代理列表、主題列表、消費組列表、每個主題對應的分割槽列表等,抑或是希望通過簡單的Web介面操作來建立一個主題或是在代理負載不均衡時,手動執行分割槽平衡操作等。為了方便對 Kafka 叢集的監控及管理,目前已有開源的 Kafka 監控及管理工具,如 Kafka Manager、Kafka Web Console、KafkaOffsetMonitor 等,讀者也可以根據自己業務需要進行定製開發。本節只簡單講解 Kafka Manager 的安裝應用。

Kafka Manager 由 yahoo 公司開發,該工具可以方便檢視叢集主題分佈情況,同時支援對多個叢集的管理、分割槽平衡以及建立主題等操作。讀者可訪問這裡進行深入瞭解。

(1)下載編譯 Kafka Manager。進入 GitHut 官網搜尋關鍵詞“kafka-manager”即可查詢到 Kafka Manager 的下載地址,直接點選“Clone or download”按鈕進行下載。將下載的 kafka-manager-master.zip 檔案上傳到 Linux 伺服器。使用者也可以在 Linux 機器上執行以下命令線上下載 Kafka Manager 原始碼:

git clone https://github.com/yahoo/kafka-manager  # 從GitHub上下載Kafka Manager原始碼

Kafka Manager 是用 Scala 語言開發的,通過 sbt(Simple Build Tool) 構建,sbt 是對 Scala 或 Java 語言進行編譯的一個工具,它類似於 Maven,Gradle。截止到編寫本書時,Kafka Manager 是基於 0.9.0.1 版本的 Kafka 開發的,鑑於 Kafka 0.9 與 Kafka-0.10 版本的實現,該版本的 Kafka Manager 也能作為 0.10.+ 版本的 Kafka 管理及監控工具,在 Kafka Manager 管理介面新增叢集管理配置時,Kafka Version 選0.9.0.1即可。待原始碼下載之後,進入 Kafka Manager 原始碼目錄,會有一個 sbt 檔案,執行以下命令進行 Kafka Manager 原始碼編譯。

./sbt clean dist      # 編譯Kafka Manager原始碼    

編譯過程會下載相關的 jar 檔案,因此有些耗時。等原始碼編譯完成後,在控制檯輸出的編譯日誌的最後幾行資訊如下:

[info] Your package is ready in /home/morton/.sbt/0.13/staging/17dfe5a6b216985c290a/   kafka-manager-master/target/universal/kafka-manager-1.3.2.1.zip[info] [success] Total time: 170 s, completed 2017-1-15 14:23:45

從控制檯輸出的編譯日誌資訊可以看到,在編譯時會在 /home/使用者名稱/路徑下建立一個.sbt 目錄,編譯後的檔案存放在該目錄相應子目錄裡,編譯日誌資訊中的 morton 為編譯 Kafka Manager 原始碼的機器名。在編譯過程中出現:

Download failed. Obtain the jar manually and place it at /home/morton/.sbt/launchers/   0.13.9/sbt-launch.jar

表示在編譯過程下載 sbt-launch.jar 檔案遇到問題,請讀者單獨下載 sbt-launch.jar 相應版本並上傳到/home/使用者名稱/.sbt/launchers/0.13.9/目錄下,再次執行編譯命令。最終會在 /home/使用者名稱/.sbt/0.13/staging 相應子目錄下生成 kafka-manager-1.3.2.1.zip 檔案,該檔案就是用來對 Kafka 進行監控和管理的工具。若讀者在編譯時由於個人網路環境原因無法編譯,可以直接在網路上下載該檔案然後複製到伺服器。將編譯好的 kafka-manager-1.3.2.1.zip 檔案解壓到指定位置(這裡解壓到 /usr/local/software/kafka-manager 目錄下)即完成安裝。

(2)修改配置。進入 Kafka Manager 安裝路徑下的 conf 目錄,開啟 application.conf 檔案,修改以下配置。將 kafka-manager.zkhosts="kafka-manager-zookeeper:2181" 配置項,修改為實際的 ZooKeeper 連線地址,例如這裡修改為:

kafka-manager.zkhosts="172.117.12.61:2181,172.117.12.62:2181,172.117.12.63:2181"

(3)啟動Kafka Manager。進入 bin 目錄下執行以下啟動命令:

nohup ./kafka-manager -Dconfig.file=../conf/application.conf &   # 啟動Kafka Manager

Kafka Manager 預設請求埠是 9000,在瀏覽器中輸入安裝 Kafka Manager 服務地址及9000埠訪問 Kafka Manager,如訪問 http://172.117.12.62:9000。Kafka Manager 啟動初始化介面如圖2-3所示。

enter image description here

圖2-3 Kafka Manager 啟動初始化介面

通過修改配置檔案 application.conf 裡 http.port 的值,或是通過命令列引數傳遞可以修改 Kafka Manager 訪問埠。例如,在啟動時指定埠為9001,啟動命令如下:

nohup ./kafka-manager -Dhttp.port=9001 -Dconfig.file=../conf/application.conf &# 修改Kafka Manager外部訪問埠號為9001

(4)關閉 Kafka Manager。Kafka Manager 沒有提供關閉操作的執行指令碼及命令,當希望關閉 Kafka Manager 時,可直接通過 kill 命令強制殺掉 Kafka Manager 程式。

檢視 Kafka Manager 程式,輸入 jps 命令,輸出以下程式資訊:

767 ProdServerStart12422 QuorumPeerMain13348 Kafka895 Jps

其中 ProdServerStart 即為 Kafka Manager 程式。通過 kill 命令關閉 Kafka Manager:

kill -9 767             # 關閉Kafka Manager程式 

同時,由於 Kafka Manager 執行時有一個類似鎖的檔案RUNNING_PID,位於 Kafka Manager 安裝路徑 bin 同目錄下,為了不影響下次啟動,在執行 kill 命令後同時刪除 RUNNING_PID 檔案,命令如下:

rm –f  RUNNING_PID      # 刪除Kafka Manager執行時的PID檔案 

否則,在下次啟動時會由於以下錯誤而導致 Kafka Manager 無法啟動。錯誤資訊如下:

This application is already running (Or delete /usr/local/software/kafka-manager/ RUNNING_PID file).

若想在 Kafka Manager 監控中能展示更多的資訊,則在 Kafka 啟動時啟動 JMX。至此,Kafka Manager 安裝講解完畢,對於 Kafka Manager 的相關操作將在5.8節進行介紹。

第02章:Kafka 安裝配置(下)

2.6 Kafka 原始碼編譯

要研究 Kafka,閱讀 Kafka 原始碼是必不可少的環節。因此,本節將介紹 Kafka 原始碼編譯及將編譯後的原始碼匯入 Eclipse 的具體步驟。當然也可以將 Kafka 原始碼匯入其他 IDE(如 Intellij Idea、STS 等)中,大家選用自己慣用的 IDE 即可。原始碼匯入步驟與匯入 Eclipse 操作基本類似,本書不再做詳細介紹。這裡只講解在 Windows 作業系統下 Kafka 原始碼的編譯,在其他作業系統上對 Kafka 原始碼的編譯操作基本類似,只不過新增環境變數操作有所不同,這裡不做講解,讀者可以查閱相關資料進行了解。由於 Kafka 核心模組是用 Scala 語言開發,用 Gradle 編譯和構建的,因此下面先介紹相關環境的安裝配置。

2.6.1 Scala 安裝配置

由於 0.10.1.1 版本的 Kafka 需要 Scala 版本在 2.10 以上,因此這裡選擇 scala-2.11.8 版本進行安裝。

(1)下載並安裝。先進入 Scala 官方網站下載相應的安裝包,下載圖2-4所示版本的 Scala。

enter image description here

圖2-4 Scala 安裝包下載列表

下載完成後,直接將安裝包解壓到指定目錄即完成安裝,安裝時解壓到 D:\software\scala- 2.11.8 目錄下。

(2)環境變數配置。安裝完成後,配置 Scala 執行環境變數,在系統變數中新增 Scala 安裝路徑配置,編輯系統變數配置如圖2-5所示。

然後將;%SCALA_HOME%\bin新增到使用者變數 path 中。與 JDK 環境安裝配置一樣,直接新增至自定義的使用者環境變數 CLASSPATH 中,如圖2-6所示。

enter image description here

圖2-5 新建SCALA_HOME變數指定Scala安裝路徑

enter image description here

圖2-6 修改 CLASSPATH 新增 Scala 環境變數

(3)驗證。Scala 安裝及環境變數配置完成後,在 Windows 下開啟一個 cmd 命令列終端。輸入檢視 Scala 版本資訊的命令:

scala  -version      # 查詢Scala版本

若輸出以下資訊則表示 Scala 安裝配置成功:

Scala code runner version 2.11.8 -- Copyright 2002-2016, LAMP/EPFL

2.6.2 Gradle 安裝配置

進入 Gradle 官方網站下載 Gradle 安裝包。本書編寫時 Gradle 的最新版本為 gradle-3.3,這裡下載的就是這個版本,讀者可以根據自己需要選擇不同版本進行下載。下載後將 Gradle 檔案解壓到相應目錄,這裡將 Gradle 解壓到 D:\software\gradle-3.3 目錄下,安裝及環境變數配置與 Scala 操作一樣,新增系統環境 GRADLE_HOME,指定 gradle 安裝路徑,並將;%GRADLE_HOME%\bin新增到 path 中,這裡依然是新增到 CLASSPATH 之中。

Gradle 安裝及環境變數配置完成之後,開啟 Windows 的 cmd 命令視窗,輸入 gradle –version,若輸出如圖2-7所示資訊,則表示 Gradle 安裝配置成功。

enter image description here

圖2-7 Gradle 安裝驗證結果

2.6.3 Kafka 原始碼編譯

先進入這裡下載 Kafka 原始碼檔案。本書編寫時 Kafka 的最新版本為 kafka-0.10.1.1,這裡我們下載的是 kafka-0.10.1.1-src.tgz,將下載的原始碼包放在 F:\kafka-0.10.1.1 目錄下,解壓後如圖2-8所示。

enter image description here

圖2-8 Kafka 原始碼解壓後的檔案目錄

進入 kafka-0.10.1.1-src,Kafka 原始碼包括圖2-9所示的目錄及檔案。

enter image description here

圖2-9 Kafka 原始碼包括的目錄及檔案

Kafka 原始碼對應目錄及檔案說明如表2-4所示。

表2-4 Kafka 原始碼對應目錄及檔案說明

名  稱描  述
bin包括 Windows 和 Linux 平臺下 Kafka 相關操作的執行指令碼,如啟動和關閉 KafkaServer、建立主題、分割槽管理、模擬生產者和消費者基本操作的指令碼等
clientsKafka 客戶端,包括 KafkaProducer 和 KafkaConsumer,用 Java 語言開發
configKafka 執行相關配置檔案,如在啟動代理時需要載入的 server.properties 檔案
connect0.9版本之後新增加的特性,提供了 Kafka 與其他系統整合進行資料匯入、匯出操作的統一介面,為 Kafka 能夠與其他系統整合構建可水平擴充套件、高可靠的資料流處理平臺提供了一個簡單模型,用Java語言開發
coreKafka 的核心程式碼,包括訊息協議定義、日誌管理、各元件之間通訊、安全協議等
docsKafka 官方網站相關文件
examplesKafka 例項程式碼
streamsKafka 0.10 版本之後增加的新特性,是一個用來構建流處理程式的庫,用Java語言開發
toolsKafka 提供的工具類,用於檢視生產者效能、吞吐量等
tests系統測試指令碼

由於在 Kafka 原始碼的 gradle 子目錄中沒有 wrapper 類庫,因此在 Kafka 根目錄下執行 gradlew eclipse 命令時會報圖2-10所示的錯誤。

enter image description here

圖2-10 Kafka 原始碼編譯出錯資訊

接下來安裝 wrapper 類庫。由於本地安裝的 Scala 版本為2.11.8,在安裝 wrapper 類庫之前,先修改 Kafka 原始碼目錄下的 gradle.properties 檔案,將 Scala 版本設定為 2.11.8。gradle.properties 檔案內容如圖2-11所示。

enter image description here

圖2-11 gradle.properties 檔案內容

然後進入 Kafka 原始碼根目錄下,執行 gradle wrapper 命令來下載 wrapper 包,如圖2-12所示。

enter image description here

圖2-12 wrapper 安裝過程輸出資訊

在該命令執行過程中會下載相應的 jar 檔案,待完成相應檔案下載後,若在控制檯列印輸出“BUILD SUCCESSFUL”字樣則表示安裝 wrapper 類庫成功。執行成功後會在 Kafka 原始碼的 gradle 目錄下生成 wrapper 目錄,如圖2-13所示。

enter image description here

圖2-13 wrapper 安裝過程建立的 wrapper 目錄

進入 wrapper 目錄,在該目錄下已建立了一個 gradle-wrapper.jar 檔案,如圖2-14所示。

enter image description here

圖2-14 wrapper 安裝過程生成的檔案

最後在 Kafka 原始碼根目錄執行 gradlew eclipse 命令,對 Kafka 原始碼進行編譯。這個過程由於要下載一系列依賴包,因此有些耗時,若出現“BUILD SUCCESSFUL”字樣,則表示編譯完成,如圖2-15所示。

enter image description here

圖2-15 Kafka 原始碼成功編譯輸出日誌資訊

若讀者在編譯時輸入 gradlew eclipse 命令後控制檯列印日誌輸出:

Downloading https://services.gradle.org/distributions/gradle-3.3-bin.zip  .........................

一直卡在下載 gradle-3.3-bin.zip 時,可通過下載工具先下載 gradle-3.3-bin.zip 檔案,然後複製到 C:\Users\使用者名稱.gradle\wrapper\dists\gradle-3.3-bin\37qejo6a26ua35lyn7h1u9v2n 目錄下,接著再次執行 gradlew eclipse 命令進行編譯。

2.6.4 Kafka 匯入 Eclipse

通過前面的步驟已完成了 Kafka 原始碼的編譯,現在介紹如何將 Kafka 原始碼匯入 Eclipse。在 Eclipse 檢視中選擇“import”,在彈出對話方塊中選擇“Existing Projects into Workspace”,指定 Kafka 原始碼路徑,依次匯入 Kafka 原始碼中的 core 和 client 工程。匯入專案後,若 Eclipse 的編碼方式不是 UTF-8,會有錯誤提示,讀者在匯入 Kafka 原始碼時要確保 Eclipse 已設定 workspase 的編碼方式為 UTF-8,同時建議修改 Scala 使用的 JVM 版本為1.8,如圖2-16所示。

Eclipse 工作空間環境配置完畢後,匯入 Kafka 的 core 和 client 工程,如圖2-17所示。

enter image description here

圖2-16 Eclipse 設定工程 Scala 執行的 JVM 版本介面

enter image description here

圖2-17 Kafka 原始碼匯入 Eclipse 效果

若在 Eclipse 中看到 core 工程有錯誤提示資訊,則在 core 工程上右鍵配置“build path”,在 Libraries 檢視下可以看到缺失如圖2-18所示的兩個檔案,這兩個檔案都是 core 工程測試程式碼所依賴的檔案,並不影響 core 工程本身的執行。這裡為了簡單,直接將這兩個檔案從 Libraries 中移除。

enter image description here

圖2-18 Kafka core 報錯所缺失的檔案

若直接執行 core 工程,kafka.kafka.scala 會報出如圖2-19所示的錯誤資訊。

enter image description here

圖2-19 Eclipse 啟動 Kafka 時在控制檯輸出的錯誤資訊

圖2-19所示的錯誤是由於 Kafka 啟動時需要載入 server.properties 檔案,用於初始化 KafkaServer,因此在執行 kafka.kafka.scala 啟動 KafkaServer 時,需要指定一個配置檔案。KafkaServer 初始化的配置這裡暫不進行詳細介紹,將穿插在第3章至第6章對 Kafka 相關知識的講解中進行介紹。現在,在 Eclipse 中設定執行引數,指定 server.properties 檔案路徑,配置如圖2-20所示。由於 Kafka 依賴 ZooKeeper,因此要保證在啟動 KafkaServer 之前先啟動 ZooKeeper。

enter image description here

圖2-20 Eclipse 設定 Kafka 啟動載入配置檔案介面

為了在控制檯輸出啟動日誌,需要將 Kafka 原始碼 config 目錄下的 log4j.properties 檔案複製到 Eclipse core 工程 src/main/scala 目錄下,執行 kafka.scala 啟動 KafkaServer,Eclipse 控制檯輸出啟動日誌資訊如圖2-21所示。

enter image description here

圖2-21 Eclipse 啟動 KafkaServer 輸出結果

圖2-21所示的日誌資訊表明:Kafka 原始碼已成功在 Eclipse 中執行起來。接下來就可以除錯 Kafka,深入瞭解 Kafka 執行機制了。

2.7 小結

本章詳細講解了 Kafka 執行環境安裝部署的步驟,包括在 Windows 作業系統、Linux 作業系統安裝部署 Kafka,以及 Kafka 視覺化管理工具的安裝和 Kafka 原始碼的編譯等。

第03章:Kafka 核心元件(上)
第03章:Kafka 核心元件(中)
第03章:Kafka 核心元件(下)
第04章:Kafka 核心流程分析(上)
第04章:Kafka 核心流程分析(中)
第04章:Kafka 核心流程分析(下)
第05章:Kafka 基本操作實戰(上)
第05章:Kafka 基本操作實戰(中)
第05章:Kafka 基本操作實戰(下)
第06章:Kafka API 程式設計實戰(上)
第06章:Kafka API 程式設計實戰(中)
第06章:Kafka API 程式設計實戰(下)
第07章:Kafka Streams(上)
第07章:Kafka Streams(中)
第07章:Kafka Streams(下)
第08章:Kafka 資料採集應用(上)
第08章:Kafka 資料採集應用(中)
第08章:Kafka 資料採集應用(下)
第09章:Kafka 與 ELK 整合應用(上)
第09章:Kafka 與 ELK 整合應用(中)
第09章:Kafka 與 ELK 整合應用(下)
第10章:Kafka 與 Spark 整合應用(上)
第10章:Kafka 與 Spark 整合應用(中)
第10章:Kafka 與 Spark 整合應用(下)

閱讀全文: http://gitbook.cn/gitchat/geekbook/5a3896efc5896e6e1cf14f19

相關文章