kafka 异常:org.apache.kafka.common.errors.UnknownTopicOrPartitionException: This server does not host

文章目录

producer 向一个之前不存在的 topic 写数据

2. UnknownTopicOrPartitionException

字面意思是:topic 或 partition 不存在。

例如:topic 一共有 3 个 partition,p0,p1,p2,而你指定向 p3写数据,则会报这个异常。

3. 问题原因分析

理论上 kafka 会自动创造不存在的 topic。

在这个场景下,producer 向一个新的 topic 写数据,则 kafka 会自动创建这个 topic,并按默认配置给出 partition。

3.1 既然会自动创建 topic,为什么还会报UnknownTopicOrPartitionException?

创建 topic 不是一个瞬间就能完成的动作,kafka 需要将 topic 信息写入 zk,zk 为了保证一致性,需要zk 集群内大部分节点都写成功。因此这个过程是需要耗费一定时间的。(未测试具体耗时)

所以当 kafka 正在创建这个 topic 的时候,producer 就向其发数据,那肯定 topic 是不存在的,因此报这个异常。

4. UnknownTopicOrPartitionException是可重试异常

根据官方 API 文档 解释:

This topic/partition doesn't exist. 
This exception is used in contexts where a topic doesn't seem to exist based on possibly stale metadata. 
This exception is retriable because the topic or partition might subsequently be created.
  • 1
  • 2
  • 3

UnknownTopicOrPartitionException是可重试异常,因为可能 topic 正在创建中,过一会就创建好了。

因此为了保证程序健壮性, producer 需要捕获此异常,并做重试。

4.1 两种重试方案

4.1.1 kafka 客户端配置

spring.kafka.producer.retries = 3

4.1.2 producer 代码捕获异常并手工重试

可以通过实现ListenableFutureCallback<SendResult<String, String>>接口,设置回调。

// 实现这个回调方法,判断 Throwable 类型,手工处理重试
void onFailure(Throwable var1);
  • 1
  • 2

参考

  1. Kafka常见错误整理 https://juejin.im/post/6844903943131103239
  2. Kafka运维填坑