![](/img/trans.png)
[英]Messages are lost on dropping and recreating kafka streams using ksql
[英]Kafka streams - KSQL - Split messages and publish to another topic
有沒有辦法使用 KSQL 將一條消息拆分為多條消息並發布到新主題。 明確地說,我不是在尋找基於 Java 的偵聽器並將其迭代/流式傳輸到新主題; 相反,我正在尋找一個為我做這件事的 KSQL。
例如:
比方說,我需要將invoice
主題中的消息拆分為item_inventory_delta
消息
關鍵:銷售支票號碼
消息示例:
{
"total": 12.33,
"salecounter": 1,
"items": [
{
"itemId": 123,
"quantity": 1
},
{
"itemId": 345,
"quantity": 5
}
]
}
鍵:saleschecknumber_itemID
消息示例
{
"itemId": 123,
"quantity": 1
}
2.
{
"itemId": 345,
"quantity": 5
}
由於添加了EXPLODE
表函數,從 ksqlDB 0.6 開始,您現在可以執行此操作。
根據您的示例給出帶有 JSON 有效負載的主題invoice
,首先使用PRINT
檢查主題以轉儲其內容:
ksql> PRINT invoice FROM BEGINNING;
Format:JSON
{"ROWTIME":1575366231505,"ROWKEY":"null","total":12.33,"salecounter":1,"items":[{"itemId":123,"quantity":1},{"itemId":345,"quantity":5}]}
然后在主題的主題上聲明一個模式,它為我們提供了一個 ksqlDB流:
CREATE STREAM INVOICE (total DOUBLE,
salecounter INT,
items ARRAY<STRUCT<itemId INT,
quantity INT>>)
WITH (KAFKA_TOPIC='invoice',
VALUE_FORMAT='JSON');
這只是“注冊”現有主題以與 ksqlDB 一起使用。 沒有新的 Kafka 主題被寫入,直到下一步。
創建一個新的 Kafka 主題,從到達源流的消息中不斷填充:
CREATE STREAM INVENTORY WITH (KAFKA_TOPIC='item_inventory_delta') AS
SELECT EXPLODE(ITEMS)->ITEMID AS ITEMID,
EXPLODE(ITEMS)->QUANTITY AS QUANTITY
FROM INVOICE;
已創建新主題:
ksql> SHOW TOPICS;
Kafka Topic | Partitions | Partition Replicas
-------------------------------------------------------------------
invoice | 1 | 1
item_inventory_delta | 1 | 1
主題有請求的增量消息:)
ksql> PRINT item_inventory_delta;
Format:JSON
{"ROWTIME":1575366231505,"ROWKEY":"null","ITEMID":123,"QUANTITY":1}
{"ROWTIME":1575366231505,"ROWKEY":"null","ITEMID":345,"QUANTITY":5}
對於KStream
應用程序,您可以使用flatMap
,它接受一個接受記錄並返回零個或多個記錄的可迭代對象的函數:
case class Record(total: Double, salecounter: Int, items: List[Item])
case class Item(itemId: Int, quantity: Int)
// initialize the stream
val inputStream: KStream[String, Record] = ???
// split the message
inputStream.flatMap { case (key, record) =>
record.items.map(item => (key, item) )
}
根據我的理解,有很多處理方法與我們如何處理傳入消息而不是聚合消息更相關。 使用 Kafka Stream Processor API 的簡單方法,它允許您自定義處理邏輯。
Processor API 允許開發人員定義和連接自定義處理器並與狀態存儲交互。 使用 Processor API,您可以定義一次處理一條接收到的記錄的任意流處理器,並將這些處理器與其關聯的狀態存儲連接起來,以組成代表自定義處理邏輯的處理器拓撲
注意:您不必定義輸出值的內容,所以我只是發布相同的鍵和值,但您可以選擇定義輸出鍵和值
您可以定義Kafka Stream處理器API如下
Topology builder = new Topology();
builder.addSource("Source", "invoice")
.addProcessor("sourceProcessor", () -> new InvoiceProcessor(), "Source")
.addSink("sinkDeltaInvoice", "item_inventory_delta", Serdes.String().serializer(), Serdes.String().serializer(),
"sourceProcessor")
以下是自定義處理器方法,請注意它只是一種方法,而不是完整的實現
class InvoiceProcessor implements Processor<String, String> {
private Gson gson = new Gson();
//constructor
.......
private ProcessorContext context;
@Override
public void init(ProcessorContext context) {
this.context = context;
}
@Override
public void close() {
// Any code for clean up would go here. This processor instance will not be used
// again after this call.
}
@Override
public void process(String key, String value) {
try {
//Create custom inventory to map JSON object
//List[Item] items is member object of Inventory class
Inventory inventory = gson.fromJson(key, Inventory.class);
//itertae item of items List[Items]
for(Item item: inventory.getItems()){
context.forward(gson.toJson(item), gson.toJson(item), To.child("sinkDeltaInvoice"));
}
//
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.