Kafka Producer NetworkException和Timeout Exceptions

时间:2017-11-06 17:46:22

标签: java apache-kafka

我们在生产环境中随机 NetworkExceptions TimeoutExceptions

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

我们偶尔会在生产者日志中获得此异常:

  

为TOPIC过期10条记录:XXXXXX:批次后已经过了5608毫秒   创造加上逗留时间。

此类错误消息中的毫秒数不断变化。有时它〜5秒其他时间它 ~13秒

我们很少得到:

NetworkException: Server disconnected before response received. 

群集由 3 经纪人 3 动物园管理员组成。生产者服务器和Kafka集群位于相同的网络中。

我正在进行同步调用。有一个Web服务,多个用户请求调用它来发送数据。 Kafka Web服务有一个Producer对象,它执行所有发送。生产者的请求超时最初 1000ms 已更改为 15000ms (15秒)。即使在增加超时期限后, TimeoutExceptions 仍会显示在错误日志中。

可能是什么原因?

4 个答案:

答案 0 :(得分:11)

找到根本原因有点棘手,我会放弃我的经验,希望有人可能会发现它有用。通常,与ack=ALL结合使用可能是网络问题或网络泛滥过多。这是一个在撰写本文时解释TimeoutException TimeoutException的图表(仍然适用于1.1.0):

Kafka KIP-91

排除网络配置问题或错误,这是您可以根据您的方案调整的属性,以便缓解或解决问题:

  • buffer.memory 控制生产者可用于缓冲的总内存。如果记录的发送速度快于传输到Kafka的速度,那么此缓冲区将被超出,然后额外的发送调用会阻塞 max.block.ms ,之后Producer会抛出<Redirect />。< / p>

  • max.block.ms 已经有一个很高的值,我不建议进一步增加它。 buffer.memory 的默认值为32MB,根据您的邮件大小,您可能需要增加它;如果需要,增加jvm堆空间。

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

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

在这类问题上没有确切的答案,因为它们也取决于实施,在我的案例中,试验上述值有帮助。

答案 1 :(得分:4)

我们也遇到过类似的问题。日志中NetworkExceptions上有许多TimeoutException

原因

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

对于TimeoutException,我们无法与发现原因时进行相同的匹配,这种错误不再发生。但是,我们在另一项测试中证实,断开TCP连接也会导致TimeoutException。我猜这是因为Java Kafka Client在后台使用Java NIO套接字通道。连接就绪后,所有消息都将被缓冲,然后分派。如果在超时(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

答案 2 :(得分:0)

解决方案1 ​​

修改

listeners=PLAINTEXT://hostname:9092
server.properties文件中的

属性为

listeners=PLAINTEXT://0.0.0.0:9092

解决方案2

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

您必须将环境变量KAFKA_RESERVED_BROKER_MAX_ID设置为1001之类的东西才能将代理ID设置为1001.

我希望它可以提供帮助

答案 3 :(得分:0)

增加制作人的 request.timeout.ms 重试次数