Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 卡夫卡之春_Java_Spring_Multithreading_Spring Kafka - Fatal编程技术网

Java 卡夫卡之春

Java 卡夫卡之春,java,spring,multithreading,spring-kafka,Java,Spring,Multithreading,Spring Kafka,我已经使用实现了Kafka consumer。 我有一个带有2个分区的Kafka主题,并且我使用了并发级别设置为2的ConcurrentKafkaListenerContainerFactory,因此每个容器实例都应该根据spring Kafka使用单个分区 KafkCamessageListenerContainer接收来自所有用户的所有消息 单个线程上的主题/分区。这个 ConcurrentMessageListenerContainer委托给1个或多个 KafkCamessageListe

我已经使用实现了Kafka consumer。 我有一个带有2个分区的Kafka主题,并且我使用了并发级别设置为2的
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。你必须接受这个事实,并根据这种情况重新设计你的解决方案