Kafka生产者在发送消息时出现了NOT_LEADER_FOR_PARTITION异常。

4
我们正在使用spring-cloud-stream-binder-kafka(3.0.3.RELEASE)将消息发送到我们的Kafka集群(2.4.1)。偶尔,其中一个生产者线程会收到NOT_LEADER_FOR_PARTITION异常,并且甚至超过重试次数(当前设置为12,由依赖项spring-retry激活)。我们限制了重试次数,因为我们每秒发送约1k个消息(每个生产者实例),并担心缓冲区的大小。
这样,我们经常会丢失消息,这对下游消费者来说是不好的,因为我们无法简单地重新生成传入的流量。
错误信息为:

[Producer clientId=producer-5] Received invalid metadata error in produce request on partition topic-21 due to org.apache.kafka.common.errors.NotLeaderForPartitionException: This server is not the leader for that topic-partition.. Going to request metadata update now
[Producer clientId=producer-5] Got error produce response with correlation id 974706 on topic-partition topic-21, retrying (8 attempts left). Error: NOT_LEADER_FOR_PARTITION
[Producer clientId=producer-5] Got error produce response with correlation id 974707 on topic-partition topic-21, retrying (1 attempts left). Error: NOT_LEADER_FOR_PARTITION

有没有已知的方法可以避免这种情况? 我们应该返回到最大重试次数的默认设置吗? 为什么它一直发送到相同的代理,尽管它以 NOT_LEADER_FOR_PARTITION 响应?

欢迎任何提示。

编辑:我们刚刚注意到,代理指标 kafka_network_requestmetrics_responsequeuetimems 在那个时间上升了,但是最大值只有大约 2.5 秒。


你能更新一下你所发现的吗? - Usul
4个回答

7

生产者和消费者请求都会发送到分区的Leader副本。当请求被发送到不是该分区当前Leader副本的分区时,会抛出NotLeaderForPartitionException异常。

客户端将每个分区的Leader信息作为缓存进行维护。完整的缓存管理过程如下图所示:

enter image description here

客户端需要通过在生产者配置中设置metadata.max.age.ms来刷新此信息。此标签的默认值为300000毫秒。

您可以查看以下Apache Kafka文档:

https://kafka.apache.org/documentation/

请查看Sender.java代码:

https://github.com/a0x8o/kafka/blob/master/clients/src/main/java/org/apache/kafka/clients/producer/internals/Sender.java

您可以在发送器代码中找到这两个错误消息。 metadata.max.age.ms的默认值为3秒。建议将其减小并观察其行为。


感谢您提供有关metadata.max.age.ms的提示,但是显示错误的日志消息也说“现在要请求元数据更新”,这意味着它不会等待间隔结束,而是立即请求新的元数据。不幸的是,重试似乎不受此影响... - smlgbl
从日志中添加了2行前置行。似乎在重试期间发生的错误甚至不会触发元数据更新,只有当重试次数超过并且异常再次出现时才会触发... - smlgbl

1

您需要正确配置监听器

我正在使用类似于docker-compose的工具

services:
  zookeeper:
    container_name: zookeeper
    ports:
      - "2181:2181"
    ...
  broker-1:
    hostname: "broker-1.mydomain.com"
    ports:
      - "29091:29091"
    ...
  broker-2:
    hostname: "broker-2.mydomain.com"
    container_name: broker-2
    ports:
      - "29092:29092"

编辑每个代理服务器的 server.properties 文件

代理服务器1

listeners: PRIVATE_HOSTNAME://broker-1.mydomain.com:9092,PUBLIC_HOSTNAME://broker-1.mydomain.com:29091
advertised.listeners: PRIVATE_HOSTNAME://broker-1.mydomain.com:9092,PUBLIC_HOSTNAME://broker-1.mydomain.com:29091
listener.security.protocol.map: PUBLIC_HOSTNAME:PLAINTEXT,PRIVATE_HOSTNAME:PLAINTEXT
inter.broker.listener.name: PRIVATE_HOSTNAME

经纪人-2

listeners: PRIVATE_HOSTNAME://broker-2.mydomain.com:9092, PUBLIC_HOSTNAME://broker-2.mydomain.com:29092
advertised.listeners: PRIVATE_HOSTNAME://broker-2.mydomain.com:9092, PUBLIC_HOSTNAME://broker-2.mydomain.com:29092
listener.security.protocol.map: PUBLIC_HOSTNAME:PLAINTEXT, PRIVATE_HOSTNAME:PLAINTEXT
inter.broker.listener.name: PRIVATE_HOSTNAME

重要提示:请注意我在私网和公网中使用相同的主机名,因为消费者/生产者只能通过此类注册名称访问kafka:

    [BrokerToControllerChannelManager broker=1 name=forwarding]: Recorded new controller, from now on will use broker broker-1.mydomain.com:9092
...
    [BrokerToControllerChannelManager broker=2 name=forwarding]: Recorded new controller, from now on will use broker broker-2.mydomain.com:9092

编辑您的主机/etc/hosts文件

127.0.0.1   broker-1.mydomain.com
127.0.0.1   broker-2.mydomain.com

1

我的解决方案(在iOS上)是:

首先杀掉zookeeper和Kafka服务器以及任何客户端,让Kafka保持安静。

cd /tmp rm -rf zookeeper Kafka-logs

然后重新启动Zookeeper,再启动Kafka。

我认为在Linux上也应该是一样的,在Windows上则需要找到存储Kafka日志和zookeeper状态文件的目录。


小心使用 rm -rf 命令。它非常强大。 - Richard Keene

0
对于窗口系统,我遇到了这样的问题:
023-10-28 14:39:32,522] WARN [Producer clientId=console-producer] Got error produce response with correlation id 6 on topic-partition topicdemo-0, retrying (2 attempts left). Error: NOT_LEADER_OR_FOLLOWER (org.apache.kafka.clients.producer.internals.Sender)
[2023-10-28 14:39:32,524] WARN [Producer clientId=console-producer] Received invalid metadata error in produce request on partition topicdemo-0 due to org.apache.kafka.common.errors.NotLeaderOrFollowerException: For requests intended only for the leader, this error indicates that the broker is not the current leader. For requests intended for any replica, this error indicates that the broker is not a replica of the topic partition.. Going to request metadata update now (org.apache.kafka.clients.producer.internals.Sender)

所以,我所做的是找到包含kafka和zookeeper的tmp文件夹,并将其删除,然后重新运行命令:
.\bin\windows\kafka-topics.bat --create --topic topicdemok --bootstrap-server localhost:9092

注意:这是我解决问题的方法,可能还有其他更有效的方法。如果有人找到了其他方法,请告诉我。谢谢。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接