非阻塞重试
2.9 版本更改了引导基础设施 bean 的机制;有关如今引导该功能所需的两种机制,请参阅 配置。
使用 Kafka 实现非阻塞重试 / DLT 功能,通常需要设置额外的主题,并创建和配置相应的监听器。自 2.7 起,Spring for Apache Kafka 通过 @RetryableTopic 注解和 RetryTopicConfiguration 类为此提供支持,以简化引导过程。
自 3.2 起,Spring for Apache Kafka 支持对类上的 @KafkaListener 使用非阻塞重试。
非阻塞重试不支持批监听器。
非阻塞重试不能与容器事务结合使用。
章节摘要
该模式的工作原理
如果消息处理失败,该消息会被转发到一个带有退避时间戳的重试主题。然后重试主题的 消费者会检查该时间戳,如果尚未到期,就暂停该主题分区的消费。到期后恢复该分区的 消费,消息被再次消费。如果消息处理再次失败,该消息将被转发到下一个重试主题,如此 重复,直到处理成功,或重试次数耗尽,消息被发送到死信主题(如果已配置)。
退避延迟精度
所有消息处理和退避均由消费者线程处理,因此延迟精度仅尽力保证。如果一条消息的 处理时间超过了该消费者下一条消息的退避时长,那么下一条消息的延迟将高于预期。 此外,对于较短的延迟(约 1 秒或更短),线程必须执行的维护工作(例如提交偏移量) 可能会延迟消息处理的执行。如果重试主题的消费者正在处理多个分区,精度也可能受到 影响,因为我们依赖将消费者从轮询中唤醒并拥有完整的 pollTimeout 来进行时序调整。
配置
对于默认设置,通过在 @KafkaListener 方法上添加 @RetryableTopic 注解来启用非阻塞 重试。这是推荐且最简单的方式,因为它会自动配置所需的重试基础设施,并使用默认设置 创建重试主题和 DLT 主题。
编程式构建
该功能设计为与 @KafkaListener 一起使用;不过,有多位用户询问如何以编程方式配置 非阻塞重试。下面的 Spring Boot 应用程序提供了一个这样做的示例。
功能
大多数功能同时适用于 @RetryableTopic 注解和 RetryTopicConfiguration bean。
组合阻塞与非阻塞重试
从 2.8.4 开始,你可以配置框架同时使用阻塞和非阻塞重试。例如,你可以设定一组 异常,它们很可能也会在后续记录上触发错误,例如 DatabaseAccessException,这样你 就可以在将同一条记录发送到重试主题或直接发送到 DLT 之前,先重试几次。
访问投递次数
要访问阻塞和非阻塞投递次数,请将以下这些头添加到你的 @KafkaListener 方法签名中:
主题命名
重试主题和 DLT 的命名方式是:在主主题后面附加一个提供的或默认的值,再附加该主题的 延迟或索引。
多个监听器、相同主题
从 3.0 版本开始,现在可以在相同主题上配置多个监听器。为此,你必须使用自定义主题 命名,使各重试主题彼此隔离。下面用一个示例来说明:
DLT 策略
框架提供了几种处理 DLT 的策略。你可以提供一个用于 DLT 处理的方法,使用默认的日志 方法,或者完全不使用 DLT。此外,你还可以选择 DLT 处理失败时的行为。
指定 ListenerContainerFactory
默认情况下,RetryTopic 配置将使用 @KafkaListener 注解中提供的工厂,但你可以指定 另一个工厂,用于创建重试主题和 dlt 监听器容器。
在运行时访问主题信息
自 2.9 起,你可以通过注入提供的 DestinationTopicContainer bean 在运行时访问有关 主题链的信息。该接口提供方法来查找链中的下一个主题,或在已配置时查找某主题的 DLT,以及主题名称、延迟和类型等有用属性。
更改 KafkaBackOffException 日志级别
当重试主题中的消息尚未到消费时间时,会抛出 KafkaBackOffException。此类异常默认 以 DEBUG 级别记录日志,但你可以通过在 @Configuration 类中的 ListenerContainerFactoryConfigurer 上设置错误处理器定制器来更改此行为。