Java 卡夫卡之春
我已经使用实现了Kafka consumer。 我有一个带有2个分区的Kafka主题,并且我使用了并发级别设置为2的Java 卡夫卡之春,java,spring,multithreading,spring-kafka,Java,Spring,Multithreading,Spring Kafka,我已经使用实现了Kafka consumer。 我有一个带有2个分区的Kafka主题,并且我使用了并发级别设置为2的ConcurrentKafkaListenerContainerFactory,因此每个容器实例都应该根据spring Kafka使用单个分区 KafkCamessageListenerContainer接收来自所有用户的所有消息 单个线程上的主题/分区。这个 ConcurrentMessageListenerContainer委托给1个或多个 KafkCamessageListe
ConcurrentKafkaListenerContainerFactory
,因此每个容器实例都应该根据spring Kafka使用单个分区
KafkCamessageListenerContainer接收来自所有用户的所有消息
单个线程上的主题/分区。这个
ConcurrentMessageListenerContainer委托给1个或多个
KafkCamessageListenerContainer s提供多线程消费
这是我的消费类课程:
@Component
public class KafkaConsumer {
private HashMap<String, LinkedBlockingQueue<Event>> hashMap = new HashMap<>();
@KafkaListener(topics = "${kafka.topic}", groupId = "events_group")
public void receive(ConsumerRecord<?, ?> record, Consumer consumer) throws InterruptedException {
String message = record.value().toString();
Event event = EventFactory.createEvent(message);
String customerId = event.getAttributeStringValue(DefinedField.CUSTOMER_ID);
// add event to hashMap
LinkedBlockingQueue<Event> queue = hashMap.get(customerId);
if (queue == null) {
queue = new LinkedBlockingQueue<>();
queue.add(event);
hashMap.put(customerId, queue);
} else {
queue.add(event);
}
}
}
@组件
公共类卡夫卡消费者{
私有HashMap HashMap=新HashMap();
@KafkaListener(topics=“${kafka.topic}”,groupId=“事件组”)
public void receive(ConsumerRecord记录,Consumer Consumer)抛出InterruptedException{
字符串消息=record.value().toString();
Event-Event=EventFactory.createEvent(消息);
字符串customerId=event.getAttributeStringValue(DefinedField.CUSTOMER\u ID);
//将事件添加到hashMap
LinkedBlockingQueue队列=hashMap.get(customerId);
if(队列==null){
队列=新的LinkedBlockingQueue();
添加(事件);
put(customerId,queue);
}否则{
添加(事件);
}
}
}
如您所见,我有一个“hashMap”集合,我根据消息“customer_id”属性将我的事件放入相应的队列中。
在多线程访问的情况下,这种功能需要额外的同步,正如我看到的,SpringKafka只为所有容器创建一个bean实例,而不是为每个容器创建一个单独的bean实例,以避免并发问题
如何以编程方式更改此逻辑
我认为解决这个问题的唯一奇怪方法是使用两个JVM运行一个单独的应用程序,其中包含单线程使用者,因此使用#receive方法访问Kafkanconsumer类将是单线程的。这是正确的。这就是它的工作原理。该框架实际上并不依赖于bean,而是依赖于它的方法来向函数传递消息
KafkaListener主题中的每个分区可以考虑两个“代码> > @ < /COD>方法。的确,来自一个分区的记录在单个线程中被传递到
@KafkaListener
。因此,如果你真的无法忍受这种状态,你可以为每个线程使用两个HashMap
侦听器抽象背后的一般思想正是关于无状态行为的。KafkaConsumer是常规的Spring单例bean。你必须接受这个事实,并根据这种情况重新设计你的解决方案