使用批量监听器的安全方式

时间:2018-05-08 13:02:02

标签: java spring apache-kafka

我正在尝试使用spring-kafka 1.3.x(1.3.3和1.3.4)。目前尚不清楚的是,当发生异常(例如网络中断)时,是否存在批量使用消息而不跳过消息(或消息集)的安全方法。我的偏好也是尽可能利用容器功能保留在Spring框架中,而不是试图创建一个自定义框架来应对这一挑战。

我将以下属性设置为ConcurrentMessageListenerContainer: .setAckOnError(false); .setAckMode(AckMode.MANUAL);

我还设置了以下kafka特定的消费者属性:

enable.auto.commit=false auto.offset.reset=earliest

如果我设置了RetryTemplate,我会得到一个类强制转换异常,因为它只适用于非批量使用者。文档状态重试不适用于批处理,因此可能没问题。

然后我设置了一个像这样的消费者: ```的java

@KafkaListener(containerFactory = "conatinerFactory",
                   groupId = "myGroup",
                   topics = "myTopic")
    public void onMessage(@Payload List<Entries> batchedData,
            @Header(required = false,
                    value = KafkaHeaders.OFFSET) List<Long> offsets,
            Acknowledgment ack) {
        log.info("Working on: {}" + offsets);
        int x = 1;
        if(x == 1) {
            log.info("Failure on: {}" + offsets);
            throw new RuntimeException("mock failure");
        }

        // do nothing else for now

        // unreachable code        
        ack.acknowledge();

   }

```

当我向系统发送消息以模拟上面的异常时,对我来说唯一可见的操作是监听器报告异常。

当我向系统发送另一条(新)消息时,容器会消耗新消息。由于偏移量已提前到下一个偏移量,因此将跳过旧消息。

由于我已经要求容器不要(直接或间接)确认,并且由于没有其他属性可以通知容器不能推进,所以我很困惑为什么容器会提前。

我注意到,对于类似的考虑,建议的是升级到2.1.x并使用添加到ContainerAware ErrorHandler中的容器停止功能。

但是,如果你暂时被困在1.3.x中,是否有一种方法或缺失的属性可用于确保容器不会前进到下一条消息或一批消息?

我可以看到围绕消费者创建自定义框架的选项,以达到预期的效果。但是还有其他选择,更简单,更适合春天。

思想?

1 个答案:

答案 0 :(得分:0)

来自@garyrussell(spring-kafka github项目)

尚未提交偏移量,但代理商不会再次发送数据。您必须重新搜索主题/分区。

2.1提供了SeekToCurrentBatchErrorHandler,它将自动为您重新搜索。

2.0添加了支持消费者的侦听器,使您可以访问侦听器中的消费者(寻求)。

使用1.3.x,您必须自己实现ConsumerSeekAware并执行搜索(在捕获异常后在侦听器中)。在ThreadLocal中保存ConsumerSeekCallback。

您需要将分区添加到方法签名中;然后寻找列表中每个分区的最低偏移量。