簡體   English   中英

Kafka 流 - 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
        }
    ]
}

item_inventory_delta主題

:saleschecknumber_itemID

消息示例

1.

{
    "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 的簡單方法,它允許您自定義處理邏輯。

Kafka 流處理器 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM