通过可重试/恢复的Spring Cloud Stream Kafka DLQ

时间:2018-07-20 22:27:29

标签: spring-cloud spring-cloud-stream spring-kafka spring-retry

我的用例是接收Kafka消息,多次尝试进行一次休息呼叫,并在用尽后将失败的消息转储到Kafka DLQ主题上。

    @StreamListener(EventSource.SOME_CHANNEL)
    public void processMessage(Message<?> unsolicitedMessage) {
         String aString = .....   
         oneService.act(aString);      
    }

@Retryable在多次尝试的处理逻辑方面运行良好。

    @Retryable(value = {OneException.class, TwoException}, maxAttempts = 3, 
    backoff = @Backoff(delay = 1000))
    public boolean act(String message, String endPoint) {
         //do stuff
    }

要使Spring Cloud Stream内置的Kafka DLQ发布开始(enableDlq: true),则需要将异常冒泡到@StreamListener注释的方法中,以使Kafka活页夹能够执行必要的操作。

但是,这样做时,我无法利用带有注释的@Recover方法,该方法在重试后将流完美地放置在

@Recover
public boolean recoverOnToDLQ(OneException ex, String message, String 
endPoint) {
    throw ex; //Required for StreamListener Kafka DLQ to kick in! 
}

问题:是否有一种方法可以从@Recover方法中触发Kakfa DLQ发布而无需重新引发异常?

因为我仅将其用于重新抛出,所以我相信我不会有效利用其中获得的更严格的控制。这还将简化单元测试用例,并更好地捕获代码级的逻辑吗?关于如何更好地处理此问题,是否有任何想法?

到目前为止,我正在使用spring-cloud,spring-cloud-stream和spring-retry的所有最新版本。

1 个答案:

答案 0 :(得分:1)

可以做到,但是问题是“你为什么想要?”。

活页夹已重试内置;只需将异常扔回给活页夹,重试用尽后它将把数据发送到DLQ。使用活页夹使用者重试属性配置重试。您不需要一行其他代码。

通过使用RetryTemplate,您将嵌套2个maxAttempts(除非您通过将使用者ErrorMessage属性设置为1来禁用活页夹重试)。

当然,您可以配置自己的DLQ目标,只需在恢复器中写入所需内容即可。但是,要使用活页夹的内置DLQ发布者,您必须制作一个特殊的ConsumerRecord(具有发布者所需的属性)并将其发送到绑定的错误通道。发布者需要原始的kafka RetryTemplate @Bean,您必须重新创建它们,因为监听者无法使用。

所有方面,对于您的用例,仅使用活页夹的重试配置似乎要简单得多。

编辑

在2.0.x中,您可以向应用程序中添加一个@StreamRetryTemplate,它将用于所有使用者绑定(覆盖绑定属性)。

可以使用任何重试策略,可重试的异常等自定义此模板。

在2.0.2版本中,必须使用RetryTemplate进行限定;之所以修复此问题,是因为任何 {{1}}会覆盖属性,而这可能不是您想要的行为。