Kafka 處理器客戶端介紹
【編者按】本文作者為 Bill Bejeck,主要介紹如何有效利用新的 Apache Kafka 客戶端來滿足資料處理需求。文章系國內 ITOM 管理平臺 OneAPM 編譯呈現,以下為正文。
如果你使用的系統需要傳輸大量資料,就算你沒用過 Kafka,很有可能已經聽說過它了。從較高層面來說,Kafka 是一個對錯誤零容忍、分散式的釋出訂閱資訊系統,設計目的是提供高速服務及處理成千上萬資訊的能力。Kafka 提供多種應用,其中一種是實時處理。實時處理通常包括讀取主題(源)的資料進行分析或轉換工作,然後將結果寫入另一個主題(sink)。目前要完成這些工作,你有以下兩種備選:
- 通過 KafkaConsumer 使用自定義程式碼來讀取資料,然後通過 KafkaProducer 寫出資料。
- 使用發展成熟的流處理框架,例如 Spark Steaming、Flink 或者 Storm。
雖然兩種方法都很好,在某些情況下,如果能有一個處於兩種之間的方法就更好了。為此,《Kafka 改進方案》流程提出了一個處理器介面。處理器介面的目的是引入一個客戶端,以便處理 Kafka 消耗的資料,並將結果寫入 Kafka。該處理器客戶端包括兩個組成部分:
- 一個“低層級”的處理器,能夠提供資料處理、組合處理和本地狀態儲存的介面
- 一個“高層級”的流 DSL,能夠滿足大部分處理執行需求。
接下來將會有一系列文章介紹新的 Kafka 處理器客戶端,本文主要介紹“低層級”的處理器功能。在後續文章中,將會介紹“高層級”的 DSL 和涉及到其它技術的高階用例。如想了解處理器客戶端的動機和目標的完整描述,請閱讀《方案》原文。免責宣告:本人與 Confluent 並無任何關係,僅僅是 Kafka 的一名熱心使用者。
處理器介面的潛在用例
在筆者看來,處理器介面是個有用工具的原因有以下幾點:
- 在處理奇異值時需要發出通知或警報。換句話說,業務需求就是:你不需要建立模型或在其它被處理的資料語境中檢查這個值。舉個例子,當有人使用虛假信用卡時,你希望能立即收到通知。
- 在進行分析時篩選資料。理想狀態下,篩選出中到高比例的資料應該重新分割槽,來避免資料傾斜問題。分割槽操作成本很高,因此通過篩選哪些資料要傳送到你的分析群集,就可以省去篩選和重新分割槽步驟。
- 你只想對源資料的某一部分進行分析,同時把所有資料傳輸到另一個儲存空間。
第一個處理器範例
在第一個處理器範例中,筆者要轉化虛構的客戶購買資料,並進行以下操作:
- 掩藏信用卡號的處理器。
- 用於收集客戶名字和消費金額的處理器,這些資訊將會用於一個獎勵專案。
- 用於收集郵編和購買商品的處理器,這些資訊可以幫助判斷消費者的購物模式。
以下是處理器物件的簡要介紹。三個處理器都繼承了 AbstractProcessor 類,該類提供了punctuate
和 close
方法的空操作重寫。在本範例中,只需要實現 process
方法,該行為就會執行到每條資訊。任務完成後,將會呼叫 context().forward
方法,它會將修改後的或者新的鍵值對轉發給下游的消費者。(context()
方法會檢索 init
方法在父類中預置的 context
例項變數)。然後, context().commit
方法被呼叫,提交包括資訊偏移在內的流當前狀態。
打造處理器圖形
現在需要定義有向無環圖(DAG)來決定資訊的流向。這是關係到處理器介面是否會“出現偏差”的地方。要打造處理器節點圖,需要用到拓撲構造器(ToplogyBuilder)。雖然筆者的資訊屬於 JSON,但還是需要定義 序列化 和 反序列化例項,因為處理器按照型別來處理。下面是來自 PurchaseProcessorDriver的一部分程式碼,它們構成了圖形拓撲、序列化程式和反序列化程式。
//Serializers for types used in the processors
JsonDeserializer<Purchase> purchaseJsonDeserializer = new JsonDeserializer<>(Purchase.class);
JsonSerializer<Purchase> purchaseJsonSerializer = new JsonSerializer<>();
JsonSerializer<RewardAccumulator> rewardAccumulatorJsonSerializer = new JsonSerializer<>();
JsonSerializer<PurchasePattern> purchasePatternJsonSerializer = new JsonSerializer<>();
StringDeserializer stringDeserializer = new StringDeserializer();
StringSerializer stringSerializer = new StringSerializer();
TopologyBuilder topologyBuilder = new TopologyBuilder();
topologyBuilder.addSource("SOURCE", stringDeserializer, purchaseJsonDeserializer, "src-topic")
.addProcessor("PROCESS", CreditCardAnonymizer::new, "SOURCE")
.addProcessor("PROCESS2", PurchasePatterns::new, "PROCESS")
.addProcessor("PROCESS3", CustomerRewards::new, "PROCESS")
.addSink("SINK", "patterns", stringSerializer, purchasePatternJsonSerializer, "PROCESS2")
.addSink("SINK2", "rewards",stringSerializer, rewardAccumulatorJsonSerializer, "PROCESS3")
.addSink("SINK3", "purchases", stringSerializer, purchaseJsonSerializer, "PROCESS");
//Use the topologyBuilder and streamingConfig to start the kafka streams process
KafkaStreams streaming = new KafkaStreams(topologyBuilder, streamingConfig);
streaming.start();
There’s several steps here, so let’s do a quick walkthrough
上面的程式碼涉及到幾個步驟,以下是其簡介:
- 在第11行有個源節點叫做“SOURCE”,一個用於鍵的 StringDeserializer 以及生成的 JsonSerializer 來處理 Purchase 物件,和供給原始碼的1到N個主題。本範例中使用的是1個主題“src-topic”的輸入資訊。
- 接下來開始新增處理器節點。
addProcessor
方法以一個 Strings 命名,一個 ProcessorSupplier,以及1到N個父節點。在本範例中,第一個處理器是“SOURCE”節點的孩子,同時又是後兩個處理器的父親。在這裡需要注意 ProcessorSupplier 的句法。該程式碼在利用方法處理(method handles),後者可以在 Java8中用作供應例項的 lambda 表示式。程式碼繼續用同樣的方式定義接下來的兩個處理器。 - 最後新增 sink(輸出主題)來完成資訊通道。
addSink
方法用到一個 String 名字、主題名字、鍵值序列化程式、值序列化程式和1到 N 個父節點。在3個addSink
方法中,可以看到之前在程式碼中建立的 JSONDeserializer 物件。
下面是拓撲構造器(TopologyBuilder)的最終結果圖示:
狀態處理器
處理器介面並不僅限於處理當前收到的值,還能維護集合、總和過程中使用的狀態,或者連線將要收到的資訊。為了充分利用狀態處理功能,在建立處理拓撲時,使用 TopologyBuilder.addStateStore
方法建立一個 KeyValueStore。可以建立兩種儲存區:(1)記憶體式的;(2)利用堆外儲存的 RocksDB 儲存。選擇哪個取決於值的有效時長。對於數量較多的動態值,RocksDB 比較適合,對於時效較短的詞條,記憶體式更適合。在指定 String、Integer 或較長的鍵值和值時,Stores 類別提供序列化、反序列化例項。但是如果使用自定義型別的鍵值或值時,需要提供自定義的序列化程式和反序列化程式。
狀態處理器範例
在本範例中,將會看到 process
方法和另外兩個重寫方法:init
和 punctuate
。process
方法抽取股票代號,更新或建立交易資訊,然後把彙總結果放入儲存區。
在 init
方法中的操作有:
- 設定 ProcessorContext 引用。
- 用
ProcessorContext.schedule
方法,以便控制punctuate
方法的執行頻率。在本範例中頻率為10秒1次。 - 給構建
TopologyBuilder
(下文將會談到)時建立的狀態儲存區設定一個引用。
punctuate
方法會迭代儲存區內的所有值,並且一旦它們在過去11秒內更新,StockTransactionSummary 物件就會被髮送給消費者。
利用狀態儲存區打造一個拓撲構造器
跟前面的例子一樣,看處理器程式碼只完成了一半的工作。以下是部分原始碼,建立了 TopologyBuilder
,其中包括一個 KeyValueStore
:
TopologyBuilder builder = new TopologyBuilder();
JsonSerializer<StockTransactionSummary> stockTxnSummarySerializer = new JsonSerializer<>();
JsonDeserializer<StockTransactionSummary> stockTxnSummaryDeserializer = new JsonDeserializer<>(StockTransactionSummary.class);
JsonDeserializer<StockTransaction> stockTxnDeserializer = new JsonDeserializer<>(StockTransaction.class);
JsonSerializer<StockTransaction> stockTxnJsonSerializer = new JsonSerializer<>();
StringSerializer stringSerializer = new StringSerializer();
StringDeserializer stringDeserializer = new StringDeserializer();
builder.addSource("stocks-source", stringDeserializer, stockTxnDeserializer, "stocks")
.addProcessor("summary", StockSummary::new, "stocks-source")
.addStateStore(Stores.create("stock-transactions").withStringKeys()
.withValues(stockTxnSummarySerializer,stockTxnSummaryDeserializer).inMemory().maxEntries(100).build(),"summary")
.addSink("sink", "stocks-out", stringSerializer,stockTxnJsonSerializer,"stocks-source")
.addSink("sink-2", "transaction-summary", stringSerializer, stockTxnSummarySerializer, "summary");
System.out.println("Starting KafkaStreaming");
KafkaStreams streaming = new KafkaStreams(builder, streamingConfig);
streaming.start();
System.out.println("Now started");
這段程式碼在建立序列化、非序列化和拓撲構造器方面並無不同。但是有一點不同。第13、14行建立了一個記憶體儲存區(命名為“summary”),供處理器使用。傳到 Stores.create
方法的名字跟前面在處理器 init
方法中用來重寫儲存區的名字一樣。在指定鍵值時,可以使用便捷的 Stores.withStringKeys()
方法,因為 Strings 本來就是它支援的型別,不需要提供引數。但是因為使用了型別化的值,所以使用了 withValues
方法,並提供了序列化和非序列化例項。
用範例程式碼執行處理器
本文所示範例可與實時 Kafka 群集進行對比。指導說明參見本文的 github 資源庫。
結論
目前為止,筆者已經介紹了 Kafka 處理器介面的“低層級”部分。希望能讓大家領略到這個新介面能夠給 Kafka 的新老使用者帶來的實用性和多樣性。在下一篇文章中,筆者將會介紹“高層級”的 DSL 介面,以及連線、時窗功能等問題。最後要強調的一點,就是處理器介面和 Kafka 流還在繼續開發中,很快將會有更新。
本文系 OneAPM 工程師整理呈現。OneAPM 能為您提供端到端的應用效能解決方案,我們支援所有常見的框架及應用伺服器,助您快速發現系統瓶頸,定位異常根本原因。分鐘級部署,即刻體驗,效能監控從來沒有如此簡單。想閱讀更多技術文章,請訪問 OneAPM 官方技術部落格。
本文轉自 OneAPM 官方部落格
原文地址:https://dzone.com/articles/introducing-the-kafka-processor-client
相關文章
- Java中的幾種Kafka客戶端比較介紹JavaKafka客戶端
- 部落格客戶端介紹客戶端
- Redis介紹 && Java客戶端操作RedisRedisJava客戶端
- Solr的Scala客戶端(scalikesolr)介紹Solr客戶端
- kafka消費者客戶端Kafka客戶端
- solr8.6.2 客戶端介面介紹及配置中文分詞器Solr客戶端中文分詞
- Jenkins 常用 REST API介紹(Java 客戶端)JenkinsRESTAPIJava客戶端
- Memcache客戶端庫libmemcached介紹和部署客戶端IBM
- python socketserver處理客戶端的流程PythonServer客戶端
- Redis 是如何處理命令的(客戶端)Redis客戶端
- ZooKeeper客戶端事件序列化處理客戶端事件
- 客戶端無法同步時間伺服器問題處理客戶端伺服器
- BitTorrent 客戶端 Deluge 2.0 釋出:新功能介紹客戶端
- [TEAP早期試讀]真正的好處:客戶端批量處理客戶端
- 跨平臺 C/C++ memcached 客戶端 memcacheclient 介紹C++客戶端client
- 記筆記:C# Socket客戶端監聽伺服器端處理方案【同步】筆記C#客戶端伺服器
- nginx 處理客戶端請求的完整過程Nginx客戶端
- 專案分享九:客戶端的異常處理客戶端
- kafka視覺化客戶端工具(Kafka Tool)的基本使用Kafka視覺化客戶端
- 如果呼叫遠端遠端url介面為https,且存在客戶端證書驗證,如何在客戶端處理HTTP客戶端
- kafka介紹Kafka
- Kafka 介紹Kafka
- 查詢GBase XDM Cluster的客戶端示例程式介紹客戶端
- 龍芯1B晶片處理器介紹晶片
- 龍芯1A處理器引數介紹
- 龍芯1D晶片處理器介紹晶片
- 對客戶又是供應商的客戶清賬處理
- iOS系統及客戶端軟體測試的基礎介紹iOS客戶端
- 事件流處理 (ESP) 與 Kafka 簡介事件Kafka
- 網路傳輸時間和客戶端處理時間的界定(批處理應用)客戶端
- 客戶預付款處理和設定
- MT6771晶片資料/處理器介紹晶片
- MT6177晶片資料/處理器介紹晶片
- 聯發科平板晶片,MT8163處理器介紹晶片
- 一、kafka 介紹 && kafka-clientKafkaclient
- 以太坊學習筆記————6、以太坊客戶端選擇與介紹筆記客戶端
- MySQL的可插入驗證和客戶端明文驗證外掛介紹MySql客戶端
- 分散式訊息系統Kafka Java客戶端程式碼分散式KafkaJava客戶端