Kafka Producer NetworkException和超时异常

Posted

技术标签:

【中文标题】Kafka Producer NetworkException和超时异常【英文标题】:Kafka Producer NetworkException and Timeout Exceptions 【发布时间】:2018-04-18 23:05:24 【问题描述】:

我们在生产环境中随机获得 NetworkExceptionsTimeoutExceptions

Brokers: 3
Zookeepers: 3
Servers: 3
Kafka: 0.10.0.1
Zookeeeper: 3.4.3

我们偶尔会在我的生产者日志中收到此异常:

TOPIC:XXXXXX 的 10 条记录到期:自批处理以来已过去 5608 毫秒 创造加上逗留时间。

此类错误消息中的毫秒数不断变化。有时是 ~5 秒,有时是 ~13 秒

我们很少得到:

NetworkException: Server disconnected before response received. 

集群由 3 brokers3 zookeepers 组成。生产者服务器和 Kafka 集群在同一网络中。

我正在同步调用。有一个 Web 服务,多个用户请求调用它来发送他们的数据。 Kafka Web 服务有一个 Producer 对象来完成所有的发送。 Producer 的请求超时最初为 1000ms,现已更改为 15000ms(15 秒)。即使在延长超时时间后 TimeoutExceptions 仍然出现在错误日志中。

可能是什么原因?

【问题讨论】:

也许你应该尝试延长你的请求超时时间看看有什么作用。 你使用的是哪个kafka版本? 当然,会尝试的。令我惊讶的是,这是一个预生产环境。我们的负载非常少。每天不超过 100,000 条消息。这是因为网络拥塞吗?如此低的负载,网络是否会变得拥塞? @NayanSharma 我们正在使用 kafka 0.10.0.1 我也遇到了同样的问题,请问您找到原因和解决方法了吗? 【参考方案1】:

找到根本原因有点棘手,我将放弃我的经验,希望有人会发现它有用。一般来说,这可能是网络问题或网络泛滥与ack=ALL 结合使用。这里有一张图表解释了撰写本文时Kafka KIP-91 中的TimeoutException(在 1.1.0 之前仍然适用):

不包括网络配置问题或错误,您可以根据具体情况调整以下属性以缓解或解决问题:

buffer.memory 控制生产者可用于缓冲的总内存。如果记录的发送速度比传输到 Kafka 的速度快,并且此缓冲区将被超出,那么额外的发送调用会阻塞到 ma​​x.block.ms,然后 Producer 会抛出 TimeoutException

ma​​x.block.ms 的值已经很高,我不建议进一步增加它。 buffer.memory 的默认值为 32MB,根据您的消息大小,您可能需要增加它;如有必要,增加 jvm 堆空间。

重试次数定义在放弃之前尝试重新发送记录的次数以防出错。如果您使用零重试,您可以尝试通过增加此值来缓解问题,请注意记录顺序不再保证,除非您将 ma​​x.in.flight.requests.per.connection 设置为 1。

一旦达到批量大小或超过逗留时间(以先到者为准),就会发送记录。如果 batch.size(默认 16kb)小于最大请求大小,您可能应该使用更高的值。此外,将 linger.ms 更改为更高的值,例如 10、50 或 100,以优化批处理和压缩的使用。如果您使用它,这将减少网络中的洪水并优化压缩。

这类问题没有确切的答案,因为它们还取决于实现,在我的例子中,尝试上述值会有所帮助。

【讨论】:

【参考方案2】:

我们也遇到过类似的问题。日志中有很多NetworkExceptions,不时出现TimeoutException

原因

一旦我们从生产中收集 TCP 日志,结果发现,在闲置 5 分钟后,一些与 Kafka 代理(我们有 3 个代理节点)的 TCP 连接在没有通知客户端的情况下被丢弃(TCP 层上没有FIN 标志)。当客户端在此之后尝试重新使用此连接时,返回 RST 标志。我们可以轻松地将 TCP 日志中的这些连接重置与应用程序日志中的NetworkExceptions 进行匹配。

至于TimeoutException,我们无法进行与找到原因时相同的匹配,这种类型的错误不再发生。然而,我们在单独的测试中确认,断开 TCP 连接也可能导致TimeoutException。我想这是因为 Java Kafka Client 在后台使用 Java NIO Socket Channel。所有消息都被缓冲,然后在连接准备好后分派。如果连接在超时(30 秒)内未准备好,则消息将过期导致TimeoutException

解决方案

对我们而言,解决方法是将客户端的 connections.max.idle.ms 减少到 4 分钟。一旦我们应用它,NetworkExceptions 就会从我们的日志中消失。

我们仍在调查断开连接的原因。

编辑

问题的原因是 AWS NAT 网关在 350 秒后断开传出连接。

https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-troubleshooting.html#nat-gateway-troubleshooting-timeout

【讨论】:

【参考方案3】:

解决方案 1

修改

listeners=PLAINTEXT://hostname:9092

server.properties 文件中的属性到

listeners=PLAINTEXT://0.0.0.0:9092

解决方案 2

将broker.id改成1001之类的值,通过设置环境变量KAFKA_BROKER_ID来更改broker id。

您必须将环境变量 KAFKA_RESERVED_BROKER_MAX_ID 设置为类似 1001 的值,才能将代理 ID 设置为 1001。

希望对你有帮助

【讨论】:

我不认为解决方案 1 可以工作。我在代理设置中更改为 0.0.0.0 现在生产者客户端不起作用,因为服务器绑定在 0.0.0.0【参考方案4】:

增加生产者的 request.timeout.ms重试次数

【讨论】:

以上是关于Kafka Producer NetworkException和超时异常的主要内容,如果未能解决你的问题,请参考以下文章

Kafka之Producer

Kafka系列之-自定义Producer

kafka 0.10.2 消息生产者(producer)

五 Kafka producer 拦截器(interceptor) 和 六 Kafka Streaming案例

kafka producer consumer

kafka 0.8.2 消息生产者 producer