Spring cloud 如何从Spring Cloud Stream中producer.send()发送的异常中恢复

Spring cloud 如何从Spring Cloud Stream中producer.send()发送的异常中恢复,spring-cloud,spring-kafka,Spring Cloud,Spring Kafka,我们经历了以下情况: 我们有一个由3个节点组成的Kafka集群,创建的每个主题有3个分区 消息通过MessageChannel.send()发送,生成分区1的记录 充当该分区的分区领导的代理失败 默认情况下,MessageChannel.send()返回true,并且不会引发任何异常,即使KafkaProducer最终无法成功发送消息。我们观察到,在该调用后约30秒,日志中出现以下消息:自批创建加上延迟时间以来,helloworld-topic-1的10条记录因30008毫秒而过期 在我们的

我们经历了以下情况:

  • 我们有一个由3个节点组成的Kafka集群,创建的每个主题有3个分区
  • 消息通过
    MessageChannel.send()
    发送,生成分区1的记录
  • 充当该分区的分区领导的代理失败
默认情况下,
MessageChannel.send()
返回
true
,并且不会引发任何异常,即使KafkaProducer最终无法成功发送消息。我们观察到,在该调用后约30秒,日志中出现以下消息:
自批创建加上延迟时间以来,helloworld-topic-1的10条记录因30008毫秒而过期

在我们的例子中,这是不可接受的,因为我们必须确保在调用
MessageChannel.send()
返回时,所有消息最终都会传递给卡夫卡

我们打开了
spring.cloud.stream.kafka.bindings..producer.sync
true
,这与文档描述的完全一样。它阻止调用者确认传递的成功或失败(
MessageTimeoutException
InterruptedException
ExecutionException
),所有这些都由
KafkaProducerMessageHandler
控制。对于我们来说,这似乎是最好的方法,因为在我们的案例中,性能影响可以忽略不计

但是,如果抛出异常,我们是否需要自己处理重试?(例如,在我们的客户代码中使用
@Retryable

这里有一个简单的实验项目:

如果在
@StreamListener
线程上执行
send()
,并且异常被抛出到绑定器,则绑定器重试配置将执行重试

但是,由于您是在HTTP线程上执行发送,因此需要进行自己的重试(在
RetryTemplate()
的范围内调用send)或使控制器方法
@Retryable