讀 Kafka 源碼寫優雅業務程式碼:配置類

這個 Kafka 的專題,我會從系統整體架構,設計到程式碼落地。和大家一起杠源碼,學技巧,漲知識。希望大家持續關注一起見證成長!

我相信:技術的道路,十年如一日!十年磨一劍!

 

往期文章

 

Kafka 探險 – 架構簡介

Kafka 探險 – 源碼環境搭建

Kafka 探險 – Kafka 探險 –  生產者源碼分析: 核心組件

 

前言

 

首先還是看一眼 Kafka 生產者中的方法,核心分為三類:構造器,消息發送,其他。

 

image.png

 

我們今天要探討的是在構造器中初始化配置時用到的配置類,看起來是構造方法中一個不起眼的參數,但是程式碼中暗藏了很多技巧。而這些技巧應用於平時的開發,也能讓我們在寫業務程式碼的時享受到寫底層中間件的感覺,讓程式碼看起來簡潔,健壯,易擴展,有層次。

 

image.png

 

四個構造方法,其餘三個構造器最終都調用到 :KafkaProducer(ProducerConfig, Serializer<K>, Serializer<V>) 

 

第一個參數是 生產者配置類,他繼承了 AbstractConfig  , 這個配置類中大部分內容為 : 配置項的 key 和 配置項代表的含義 doc ,例如

image.png

但是還有一個非常重要的欄位: ConfigDef CONFIG  , ConfigDef 這個類定義了一份配置的元數據,並且提供了: 繼承,分組,存儲的能力。分別對應 ConfigDef 的以下三個欄位:

image.png

配置定義

 

配置存儲

 

配置存儲即通過 ConfigKey 來完成,他定義了配置的元數據,包括 數據類型,key,分組,優先順序,校驗器。通過一個抽象的 Validator  介面實現添加配置時的校驗邏輯

image.png

為每個欄位設置校驗器,各個欄位校驗器有各自的實現類,這一點可以借鑒下,對於欄位的校驗 自定義校驗器,將校驗邏輯集中封裝,而不是散落在程式碼的各個位置

image.png

 

配置繼承

 

配置的繼承實現非常簡單,直接傳遞一個配置類,將裡面存儲的配置和分組拷貝過來

image.png

 

配置分組

 

一方面通過 ConfigKey 中定義的 group 欄位,另外在定義配置項的時候將 key 與 group 的關係存放到 Map 中。

image.png

 

配置操作

 

看完了配置元數據的定義後,繼續回到構造方法 KafkaProducer(ProducerConfig, Serializer<K>, Serializer<V>) ,可以看到需要傳遞一個 ProducerConfig ,他其實就是Kafka 的配置類,而這個配置類恰巧就對應了 producer.properties 這個配置文件。看到這裡是不是發現這與 Spring 中的 JavaConfig 同 Xml 有異曲同工之妙?事實正是如此大多數框架都會有一套配置文件與 Java 類的映射關係,方便默認配置載入,或者配置的動態載入,網路載入等等…

 

生產者的配置類為 ProducerConfig 消費者為 ConsumerConfig  他們都繼承了 AbstractConfig  從下面的圖看一看到,Kafka 中所有的配置都是由這個基類來驅動的。

image.png

我們需要關注的方法主要為: 構造器、取配置值、其他

image.png

構造方法

image.png

 

整體程式碼相對比較簡單,將傳入的原始 Map 配置解析到當前類的 values 成員變數中,此時 values 也是一個 Map ,只不過他的 value 不是簡單的字元串了而是解析後的對象類型。

 

這裡需要注意的一點在於他的 postProcessParsedConfig()  方法,這個方法在當前類是一個空實現,具體的實現是在子類實現的。在有類的繼承關係的時候某些通用的前置後置操作,但是這些操作根據不同的子類需要不同的實現的時候我們經常會這麼處理,這種方法也叫做模板方法或者稱作 模板設計模式 。

 

image.png

 

取值方法

 

這些方法比較簡單,但是非常有必要。我經常在很多項目裡面看到這樣的程式碼

 

image.png

 

我相信大家都不陌生,在很多工程中都會見到這樣的程式碼,某個類中定義了一個 Map  或者一個 JSONObject  但是並沒有封裝對應值的方法,而是在使用到的時候直接 get 一個字元串,然後類型強轉。

 

這樣的程式碼顯然是低品質的程式碼,缺點很明顯我們並不知道這個 Map 都會有哪些 key,每次取數據的時候只能使用魔法字元串。另外取出來的值有可能是空,直接強壯很有可能 NPE 。需要做判空操作,強制類型轉換,這些非常常用的基礎程式碼會散落在項目的各個文件中。

 

一般來說我們最好直接定義類,少定義 Map 或者 JSON 。那麼萬一使用了我們又該如何讓他變得 易懂,易維護,易使用呢?

 

首先針對使用魔法值 get 的問題,我們需要針對這個 Map 定義一個常量,定義 Map 中所有會存儲和取出的 Key 每次如果需要往這個 Map 中寫入新的 Key 需要修改下這個常量類。

 

而對於每次根據 key 取數據,並強轉的問題我們可以定義一些基礎方法,例如 getIntExtVal()  getLongExtVal()  等等一系列的方法,將判空和強轉一併解決了甚至還可以配置默認值。簡化下大概長下面這樣,是不是程式碼瞬間清晰了很多,調用起來也變得方便了。

 

image.png

 

尾聲(嘮叨)

 

過完春節的第一個周末,終於也是寫完這篇文章了。只是好久沒有鍛煉身體了,上周打完羽毛球胳膊簡直廢了,後面要好好運動!

 

另外:大家也可以關注下我的微信公眾號哦~【 徐筆筆 】