Java 如何用锁存器包装SeektocurInterrorHandler处理的@KafkaListener以进行测试

Java 如何用锁存器包装SeektocurInterrorHandler处理的@KafkaListener以进行测试,java,spring-boot,apache-kafka,spring-kafka,spring-kafka-test,Java,Spring Boot,Apache Kafka,Spring Kafka,Spring Kafka Test,我有一个kafka侦听器,它抛出一个异常并转到SeektocurInterrorHandler进行处理。我正在尝试包装侦听器以添加一个闩锁,并在其上断言以进行测试。但它似乎不起作用。有人能推荐一下吗 听众: @KafkaListener(id="testRetry",topics = "sr1", groupId = "retry-grp", containerFactory = "kafkaRetryListenerCont

我有一个kafka侦听器,它抛出一个异常并转到SeektocurInterrorHandler进行处理。我正在尝试包装侦听器以添加一个闩锁,并在其上断言以进行测试。但它似乎不起作用。有人能推荐一下吗

听众:

@KafkaListener(id="testRetry",topics = "sr1", groupId = "retry-grp", containerFactory = "kafkaRetryListenerContainerFactory")
    public void listen1(ConsumerRecord<String, Anky> record,
            @Header(KafkaHeaders.DELIVERY_ATTEMPT) int delivery, Acknowledgment ack) throws UserException {
            throw new UserException(code.getDbError());

    }
@KafkaListener(id=“testRetry”,topics=“sr1”,groupId=“retry grp”,containerFactory=“kafkaRetryListenerContainerFactory”)
公共作废列表1(消费者记录记录,
@标头(KafkaHeaders.DELIVERY_-trument)int-DELIVERY,ackknowledge-ack)抛出UserException{
抛出新的UserException(code.getDbError());
}
配置:

@Bean
    public ConcurrentKafkaListenerContainerFactory<String, Anky> kafkaRetryListenerContainerFactory(SeekToCurrentErrorHandler seekToCurrentErrorHandler) {

        ConcurrentKafkaListenerContainerFactory<String, Anky> factory = new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory());
        factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
        // to get the no retry count from the header
        factory.getContainerProperties().setDeliveryAttemptHeader(true);
        factory.setErrorHandler(seekToCurrentErrorHandler);
        // to keep the consumers alive the failure gets reported to broker so that
        // consumers remain alive
        factory.setStatefulRetry(true);
        factory.setConcurrency(2);
        return factory;
    }


    @Bean
    public SeekToCurrentErrorHandler seekToCurrentErrorHandler(DeadLetterPublishingRecoverer deadLetterPublishingRecoverer) {
        SeekToCurrentErrorHandler errorHandler = new SeekToCurrentErrorHandler((record, exception) -> {
            //do nothing
        });
        errorHandler.setCommitRecovered(true);
        errorHandler.setBackOffFunction((record, exception) -> {
            return new FixedBackOff(0L,5L);

        });
        return errorHandler;
    }
@Bean
public ConcurrentKafkalListenerContainerFactory kafkaRetryListenerContainerFactory(请参阅OccurInterrorHandler SeekToccurInterrorHandler){
ConcurrentKafkListenerContainerFactory=新ConcurrentKafkListenerContainerFactory();
setConsumerFactory(consumerFactory());
factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
//要从标头获取无重试计数
factory.getContainerProperties().setDeliveryAttemptHeader(true);
factory.setErrorHandler(请参见目录InterrorHandler);
//为了保持消费者的活力,故障会报告给代理,以便
//消费者仍然活着
factory.setStatefulRetry(true);
工厂设置并发(2);
返回工厂;
}
@豆子
public SeekToCurrentErrorHandler SeekToCurrentErrorHandler(死信发布恢复器死信发布恢复器){
SeekToCurrentErrorHandler errorHandler=新的SeekToCurrentErrorHandler((记录,异常)->{
//无所事事
});
errorHandler.setCommitRecovered(true);
errorHandler.setBackOffFunction((记录,异常)->{
返回新的固定回退(0L、5L);
});
返回错误处理程序;
}
测试:

@测试
public void testRetry()引发异常,UserException{
Anky msg=新的Anky();
这个.template.send(“sr1”、“1234”、msg);
CountDownLatch闩锁=新的CountDownLatch(1);
ConcurrentMessageListenerContainer=(ConcurrentMessageListenerContainer)kafkaListenerEndpointRegistry
.getListenerContainer(“testRetry”);
container.stop();
@抑制警告(“未选中”)
AcknowledgeingConsumerRawareMessageListener messageListener=(AcknowledgeingConsumerRawareMessageListener)容器
.getContainerProperties().getMessageListener();
container.getContainerProperties()

.setMessageListener(新建确认ConsumerRawareMessageListener添加一个
try…finally

试试看{
onMessage(数据、确认、消费者);
}
最后{
倒计时();
}

如果从侦听器抛出异常,闩锁如何在那里工作?无法访问
倒计时()在finally then中,它只重试一次而不是5次…这没有意义-您是否将
CountDownLatch
增加到5?嗨,Gary,我发现有时测试不会调用消费者,并且随机失败,在jenkins构建中闩锁返回false。为什么会发生这种情况?您能否建议…这可能是一个错误ce条件,很可能是由于未将
ConsumerConfig.AUTO\u OFFSET\u RESET\u CONFIG
设置为
earlime
。它默认为
latest
,这意味着如果记录在模板发送后启动,消费者将看不到该记录。我检查过,consumer CONFIG设置为Earlime…但有时文本仍会失败…是真的吗我能做些什么来避免这种不一致?
@Test
public void testRetry() throws Exception,UserException {
    Anky msg = new Anky();
    this.template.send("sr1", "1234", msg);
    CountDownLatch latch = new CountDownLatch(1);
            ConcurrentMessageListenerContainer<?, ?> container = (ConcurrentMessageListenerContainer<?, ?>) kafkaListenerEndpointRegistry
            .getListenerContainer("testRetry");
    container.stop();
    @SuppressWarnings("unchecked")
    AcknowledgingConsumerAwareMessageListener<String, Anky> messageListener = (AcknowledgingConsumerAwareMessageListener<String, Anky>) container
            .getContainerProperties().getMessageListener();

    container.getContainerProperties()
            .setMessageListener(new AcknowledgingConsumerAwareMessageListener<String, Anky() {

                @Override
                public void onMessage(ConsumerRecord<String, Anky> data, Acknowledgment acknowledgment,
                        Consumer<?, ?> consumer) {
                    messageListener.onMessage(data, acknowledgment, consumer);
                    latch.countDown();
                }

            });
    container.start();
    assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue();
    
}