自动提交为false的Kafka使用者抛出异常,同时确认了asyc调用“ KafkaConsumer对于多线程访问不安全”

时间:2019-10-17 06:35:16

标签: apache-kafka kafka-consumer-api spring-kafka

我们正在为Kafka并发消费者将kafka自动提交为false。然后,基于使用Rest Template的Async中的另一个Microservice调用,我们尝试确认响应。在确认时,我们收到KafkaConsumer对于多线程访问不安全的错误。正在执行。

如果我们在方法中删除异步,则不会引发异常并且工作正常。

    @Async("******")
    public CompletableFuture<String> process*****Service(****** ******, String serviceUrl, Acknowledgment acknowledgment){

        ResponseEntity<String> serviceResponse = null;
        int retryCount = 0;
        String response = null;
        try {
            HttpHeaders headers = KafkaConsumerUtil.prepareHeaders(ApplicationConstant.****, apikey);
            HttpEntity<******> entity = new HttpEntity<>(*****, headers);
            retryCount++; 
            System.out.println("Attempting retry mechanism with counter "+retryCount);
            serviceResponse = restTemplate.exchange(serviceUrl, HttpMethod.POST, entity, String.class);
            if (null != serviceResponse) {
                response = serviceResponse.getStatusCode().toString();
                acknowledgment.acknowledge();
            }
        }catch (Exception e) {
            log.error(ApplicationConstant.*****.concat("Exception caught at process*****Service "+e.getMessage()));
            String producerUrl = appProperties.getKafkapropmap().get(ApplicationConstant.PUBLISHER_MS_SERVICE_URL);
//          deadLetterTopic.invokeDeadLetterTopic(****Request, producerUrl, acknowledgment);
        }
        return CompletableFuture.completedFuture(response);
    }



    @Bean
    public ConcurrentKafkaListenerContainerFactory<Long, String> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<Long, String> factory =
                new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory());
        factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
        factory.setConcurrency(Integer.parseInt(concurrency));
        return factory;
    }

    and
    props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false); 

错误

2019-10-17 11:59:03.612 [Pre-******-3] ERROR c.a.m.reg.service.******* -
                ********: Exception caught at ******Service KafkaConsumer is not safe for multi-threaded access

我们正在使用spring-kafka 1.3.0.RELEASE

任何提示都值得赞赏!

1 个答案:

答案 0 :(得分:0)

首先,您应该升级到最新的1.3.x版本(1.3.10)。

在旧版本中,您不能将await asyncio.sleep(0.1)与异步acks一起使用;您只能使用MANUAL_IMMEDIATE,它会将将要提交的主要使用者线程的ack排队。

使用者不是线程安全的。

AckMode.MANUAL仅在由调用侦听器的线程完成确认后才能使用。现在,容器会检测到哪个线程正在执行ack,并将排队异步提交。

此问题已在1.3.4中修复,但最新版本为1.3.10。