【问题标题】:ConcurrentMessageListenerContainer isn't acting concurrentConcurrentMessageListenerContainer 不是并发的
【发布时间】:2017-12-21 03:58:06
【问题描述】:

我正在尝试创建一个多线程侦听器,但所有消息都在同一个线程中执行。运行时,线程 ID 始终相同,即使认为 KafkaListerContainerFactory 是(正确)我实例化的那个。如果我几乎同时发送 7 条消息,我希望前三个同时处理,然后是接下来的三个并发处理,然后是最后一个。我看到的是第一个过程完成,然后是第二个,然后是第三个,等等。我误解了什么,或者只是配置错误?

这是我的听众:

@Component
public class ExampleKafkaController {
    Log log = Log.getLog(ExampleKafkaController.class);

    @Autowired
    private KafkaListenerContainerFactory kafkaListenerContainerFactory;

    @KafkaListener(topics = "${kafka.example.topic}")
    public void listenForMessage(ConsumerRecord<?, ?> record) {
        log.info("Got record:\n" + record.value());
        System.out.println("Kafka Thread: " + Thread.currentThread());
        System.out.println(kafkaListenerContainerFactory);

        log.info("Waiting...");
        waitSleep(10000);

        log.info("Done!");
    }

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Value("${kafka.example.topic}")
    public String topic;    

    public void send(String payload) {
        log.info("sending payload='" + payload + "' to topic='" + topic + "'");
        kafkaTemplate.send(topic, payload);
    }

    private void waitSleep(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

这是我使用新配置的应用程序:

@SpringBootApplication
@ComponentScan("net.reigrut.internet.services.example.*")
@EntityScan("net.reigrut.internet.services.example.*")
@EnableKafka
@Configuration
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Autowired 
    ConsumerFactory<Integer,String> consumerFactory;

    @Bean
    KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<Integer, String>> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<Integer, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory);
        factory.setConcurrency(3);
        System.out.println("===========>" + consumerFactory);
        System.out.println(factory);
        return factory;
    }
}

【问题讨论】:

    标签: spring-boot apache-kafka spring-kafka


    【解决方案1】:

    使用 Kafka,并发受限于主题中的分区数量。如果只有一个分区,则无论容器的并发设置如何,您都只会在一个线程上接收消息。

    您应该将分区数设置为大于或等于您想要的并发数。如果分区数大于并发数,则分区将分布在消费者线程中。

    组中只有一个消费者可以从分区消费。

    【讨论】:

    • 很棒的信息,我没有从任何文档中收集到。谢谢!只是为了确保我理解,但是消费者可以从多个分区消费,但任何一个分区只能由单个消费者消费。对吗?
    • 是的,没错;代理将分区分配给同一组中的所有消费者。您可能想要探索属性以避免在消费者启动时多次重新平衡。这里习惯使用accept answers that solve your problem - 它会帮助其他人寻找答案。
    • 我遇到了同样的问题,在检查了配置 num.partitions 和 kafka 日志目录以确认我的主题有 3 个分区后,但我仍然发现它是单线程运行的(名称如 KafkaListenerEndpointContainer#4-1-C-1 ),但我的spring.kafka.listener.concurrency5,对我有什么建议吗?非常感谢
    • 请不要评论老问题;问一个新问题并显示与分区分配相关的启动日志;默认情况下,它们被容器记录在 INFO 中。
    • 这很好,这种行为是否记录在某处?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多