如果Kafka服务器不可用,则终止Spring Kafka事务

时间:2018-07-16 10:20:23

标签: java apache-kafka spring-kafka

在我们的项目中,我们需要通过许多线程定期从第三方获取数据,然后将其推送到Kafka。而且,如果此时Kafka服务器不可用,则应终止该流,应将获取的数据丢失并在下一次计划执行期间重新获取。另外,还需要使用事务管理,因为我们需要将这批消息发送到Kafka的不同主题。如果没有发送一条消息,则所有其他消息都应回滚。

如果Kafka Server不可用,我们会遇到终止执行的问题。禁用交易管理后,一切正常,我们得到

org.apache.kafka.common.errors.TimeoutException: Failed to update metadata after 60000 ms.

但是在启用事务管理的情况下,Kafka生产者尝试无限访问服务器,并且所有发起将消息推送到Kafka的线程都将停留。我们尝试了不同的设置,以使其在一段时间不可用后失败,但这并没有帮助。 设置spring.kafka.producer.retries: 0spring.kafka.producer.acks: 0会导致(堆栈跟踪不完整):

Caused by: org.apache.kafka.common.config.ConfigException: Must set retries to non-zero when using the idempotent producer.

Caused by: org.apache.kafka.common.config.ConfigException: Must set acks to all in order to use the idempotent producer. Otherwise we cannot guarantee idempotence.

当Kafka服务器不可用并且启用了事务管理时,是否有一些设置组合会使Kafka Producer在超时后失败?那有可能吗?

1 个答案:

答案 0 :(得分:2)

Spring-Kafka使用DefaultAfterRollbackProcessor来查找失败的偏移量,然后重试-这将继续循环直到正确处理偏移量为止。这是默认行为。如果交易失败取决于您rollbackFor的{​​{1}}属性,您将回滚。

您有一个特殊情况,如果Kafka服务器不可用,它将回滚。您可以通过实现@Transactional来创建自己的处理器。由于连接超时,您将需要从回滚中识别出常规回滚。

编辑: 您还可以在AfterRollbackProcessor上定义属性noRollbackFor以排除@Transactional并使此异常到达TimeoutException。您可以创建自定义ExceptionHandler并在容器上使用Container。您可以阅读有关容器错误处理程序here

的信息。