[英]Kafka Producer NetworkException and Timeout Exceptions
我们在生产环境中收到随机的NetworkExceptions
和TimeoutExceptions
:
Brokers: 3
Zookeepers: 3
Servers: 3
Kafka: 0.10.0.1
Zookeeeper: 3.4.3
我们偶尔会在我的生产者日志中收到此异常:
过期 10 条 TOPIC:XXXXXX 记录:5608 毫秒自批处理创建以来已过去,加上逗留时间。
此类错误消息中的毫秒数不断变化。 有时它是~5 秒,有时它高达~13 秒!
我们很少得到:
NetworkException: Server disconnected before response received.
Cluster 由3 个broker和3 个zookeeper 组成。 生产者服务器和 Kafka 集群在同一网络中。
我正在进行同步调用。 有一个 Web 服务可供多个用户请求调用以发送他们的数据。 Kafka Web 服务有一个 Producer 对象来完成所有的发送。 生产者的请求超时最初是1000 毫秒,现在已更改为15000 毫秒(15 秒)。 即使在增加超时期限后TimeoutExceptions
仍然显示在错误日志中。
原因是什么?
找到根本原因有点棘手,我会放弃我的经验,希望有人会发现它有用。 通常,它可能是网络问题或与ack=ALL
结合使用过多的网络泛滥。 这是在撰写本文时解释来自Kafka KIP-91的TimeoutException
的图表(直到 1.1.0 仍然适用):
不包括网络配置问题或错误,您可以根据您的场景调整这些属性以缓解或解决问题:
buffer.memory控制生产者可用于缓冲的总内存。 如果记录的发送速度比它们可以传输到 Kafka 的速度快,那么这个缓冲区将被超过,那么在 Producer 抛出TimeoutException
之后,额外的发送调用会阻塞到max.block.ms 。
max.block.ms已经有一个很高的值,我不建议进一步增加它。 buffer.memory的默认值为 32MB,根据您的消息大小,您可能希望增加它; 如有必要,增加 jvm 堆空间。
重试定义了在出现错误的情况下在放弃之前尝试重新发送记录的次数。 如果您使用零重试,您可以尝试通过增加此值来缓解问题,请注意记录顺序不再保证,除非您将max.in.flight.requests.per.connection设置为 1。
一旦达到批量大小或经过延迟时间(以先到者为准),就会发送记录。 如果batch.size (默认16kb)小于最大请求大小,也许您应该使用更高的值。 此外,将linger.ms更改为更高的值,例如10、50或 100,以优化批处理和压缩的使用。 如果您正在使用它,这将减少网络中的泛滥并优化压缩。
此类问题没有确切的答案,因为它们还取决于实现,在我的情况下,尝试使用上述值有所帮助。
我们也遇到过类似的问题。 日志中的许多NetworkExceptions
和TimeoutException
不时发生。
原因
一旦我们从生产中收集 TCP 日志,结果发现在闲置 5 分钟后(TCP 层上没有FIN
标志),一些到 Kafka 代理(我们有 3 个代理节点)的 TCP 连接被丢弃,而没有通知客户端。 当客户端在此之后尝试重新使用此连接时,则返回RST
标志。 我们可以轻松地将 TCP 日志中的这些连接重置与应用程序日志中的NetworkExceptions
进行匹配。
至于TimeoutException
,我们无法进行与找到原因时相同的匹配,此类错误不再发生。 然而,我们在单独的测试中确认,丢弃 TCP 连接也可能导致TimeoutException
。 我想这是因为 Java Kafka Client 在底层使用 Java NIO Socket Channel。 所有消息都被缓冲,然后在连接准备好后分派。 如果连接在超时(30 秒)内未准备好,则消息将过期,导致TimeoutException
。
解决方案
对我们来说,解决方法是将我们客户端的connection.max.idle.ms减少到 4 分钟。 一旦我们应用了它, NetworkExceptions
就从我们的日志中消失了。
我们仍在调查断开连接的原因。
编辑
问题的原因是 AWS NAT 网关在 350 秒后断开传出连接。
解决方案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。
我希望它可以帮助
增加request.timeout.ms和生产者的重试
我们尝试了一切,但没有运气。
最后,我们的案例是kafka群集本身存在问题,无法从2个服务器之间获取元数据。
当我们将目标kafka集群更改为我们的开发箱时,它运行良好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.