Apache kafka 如何在卡夫卡流中动态处理并发送到不同的主题
我正在创建一个流处理应用程序。它应该创建一个kafka流连接。当信息到达时,我需要做以下几件事:Apache kafka 如何在卡夫卡流中动态处理并发送到不同的主题,apache-kafka,apache-kafka-streams,spring-kafka,Apache Kafka,Apache Kafka Streams,Spring Kafka,我正在创建一个流处理应用程序。它应该创建一个kafka流连接。当信息到达时,我需要做以下几件事: 检查消息的类型 通过调用specificTypeProcessing服务来处理消息 最后是根据消息类型确定的特定主题 public java.util.function.Consumer<KStream<String, String>> process() { String topic; return input -> inpu
- 检查消息的类型
- 通过调用specificTypeProcessing服务来处理消息
- 最后是根据消息类型确定的特定主题
public java.util.function.Consumer<KStream<String, String>> process() { String topic; return input -> input.map((key, value) -> { //check type and ask object from factory try { JSONObject msg = Util.getObjectMapper().readValue(value, JSONObject.class); String type = msg.get("type").toString(); if(type.equalsIgnoreCase("test")){ //processing started msgTypeHandlerFactory .createInstance(type) .enrichAndRelay(msg); System.out.println("IN"); } else{ input.to("notStream"); System.out.println("OUT"); } } catch (JsonProcessingException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return KeyValue.pair(key, value); }) .to("output_topic"); }
上面代码的问题是我使用的是map函数,它使我能够使用.to()函数发送流。 我想要的是检查每个消息的类型,然后进行处理,并相应地发送到另一个流。 为此,我应该使用foreach函数,它没有给我.to()函数,所以我必须创建另一个卡夫卡制作人来完成这项工作public java.util.function.Consumer进程(){ 字符串主题; 返回输入-> input.map((键,值)->{ //检查类型并向工厂询问对象 试一试{ JSONObject msg=Util.getObjectMapper().readValue(值,JSONObject.class); 字符串类型=msg.get(“type”).toString(); if(类型等信号情况(“测试”)){ //开始处理 msgTypeHandlerFactory .createInstance(类型) .继电器(msg); 系统输出打印项次(“输入”); } 否则{ 输入到(“notStream”); System.out.println(“out”); } }捕获(JsonProcessingException e){ e、 printStackTrace(); }捕获(例外e){ e、 printStackTrace(); } 返回KeyValue.pair(键,值); }) 。至(“输出主题”); }
如果要检查类型,基本上就是过滤那些与这些类型匹配的事件 因此,您不需要map或foreach,您最好使用
filter(…).to(topic}
final ObjectMapper mapper=Util.getObjectMapper();
KStream notTestEvents=input.filter((键,值)->{
//检查类型并向工厂询问对象
试一试{
JSONObject msg=mapper.readValue(value,JSONObject.class);//您可能应该改用JSONDeserializer,它可以为您实现这一点
字符串类型=msg.get(“type”).toString();
System.out.println(“out”);
return!type.equalsIgnoreCase(“测试”);
}捕获(JsonProcessingException e){
e、 printStackTrace();
}捕获(例外e){
e、 printStackTrace();
}
);
notTestEvents.to(“notStream”);
另一种选择是分支
KStream<String, String>[] branches = events.branch(
(k, v) -> {
return !mapper
.readValue(value, JSONObject.class)
.get("type").toString();
.equalsIgnoreCase("test")
},
(k, v) -> true
);
branches[0].map(...).to("notStream");
branches[1].map(...).to("output_topic");
KStream[]branchs=events.branch(
(k,v)->{
返回!地图绘制者
.readValue(值,JSONObject.class)
.get(“type”).toString();
.equalsIgnoreCase(“测试”)
},
(k,v)->正确
);
分支[0]。映射(…)。到(“notStream”);
分支[1]。映射(…)。到(“输出主题”);
branch()
。branch()
函数允许您提供固定数量的谓词,将消息路由到不同的子流中。然后您可以独立处理这些子流,例如使用map()
函数。最后,您可以使用to()
将每个子流发送到单独的主题
KStream[]branchs=events.branch(
(id,event)->event.getTransactionValue()>=欺诈限额,
(id,event)->event.getTransactionValue();
分支[0]。映射(…)。到(可疑的TransactionStopicName);
分支[1]。映射(…)。到(validatedTransactionsTopicName);
您还可以在to()
中根据事件负载中的任何内容做出真正的动态路由决策。这里,输出主题的名称来自事件数据
myStream.to(
(eventId、event、record)->“主题前缀-”+event.methodOfYourEventLikeGetTypeName()
);
此外,如果动态路由决策需要事件中不直接可用的信息,则您可以选择使用路由相关信息动态丰富原始事件(例如,通过将原始事件流与具有路由相关信息的表连接),然后通过
to()执行动态路由
。有关详细信息,请参阅。筛选器解决了选择类型的问题。但是map函数是一次处理一条记录并将其发送到输出流,还是逐个处理所有记录,然后将所有记录一次发送到输出流?我将使用它作为输入流->按类型筛选->。map函数->。to()fumctionmap和filter函数都是一个接一个的。您需要一个groupBy或其他聚合来将数据收集到更大的消息中