Spring Kafka生产者抛出TimeoutExceptions

时间:2018-06-06 16:49:53

标签: java spring-boot apache-kafka kubernetes

问题

我在Kubernetes有一个Kafka设置,有三个经纪人,根据https://github.com/Yolean/kubernetes-kafka的指南设置。从Java客户端生成消息时出现以下错误消息。

2018-06-06 11:15:44.103 ERROR 1 --- [ad | producer-1] o.s.k.support.LoggingProducerListener    : Exception thrown when sending a message with key='null' and payload='[...redacted...]':
org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for topicname-0: 30001 ms has passed since last append

详细设置

设置侦听器以允许来自外部世界的SSL生产者/消费者:

advertised.host.name = null
advertised.listeners = OUTSIDE://kafka-0.mydomain.com:32400,PLAINTEXT://:9092
advertised.port = null
listener.security.protocol.map = PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL,OUTSIDE:SSL
listeners = OUTSIDE://:9094,PLAINTEXT://:9092
inter.broker.listener.name = PLAINTEXT
host.name =
port.name = 9092

OUTSIDE监听器正在监听kafka-0.mydomain.com,kafka-1.mydomain.com等。明文监听器正在侦听任何IP,因为它们是Kubernetes的集群本地。

制作人设置:

kafka:
  bootstrap-servers: kafka.mydomain.com:9092
  properties:
    security.protocol: SSL
   producer:
    batch-size: 16384
    buffer-memory: 1048576 # 1MB
    retries: 1
    ssl:
      key-password: redacted
      keystore-location: file:/var/private/ssl/kafka.client.keystore.jks
      keystore-password: redacted
      truststore-location: file:/var/private/ssl/kafka.client.truststore.jks
      truststore-password: redacted

此外,我在代码中将linger.ms设置为100,这会强制在100毫秒内传输消息。灵活时间设置为故意低,因为用例需要最少的延迟。

分析

  • 当代理移动到SSL时,错误开始出现。
  • 在服务器端,一切都按预期运行,日志中没有错误,我可以使用Kafka客户端工具手动连接到代理。
  • 错误会间歇性地出现:有时它每秒发送30条以上的消息,有时它根本不发送任何消息。它可能会像几个小时的魅力一样,然后只是一段时间的垃圾邮件超时。
  • 客户端和服务器的时钟同步(UTC)。
  • 生产和服务器端的CPU始终保持在20%左右。

它可能是什么?

1 个答案:

答案 0 :(得分:1)

这个问题通常发生在生产者比经纪人更快的时候,你的设置发生这种情况的原因似乎是SSL需要额外的CPU,这可能会减慢经纪人的速度。但无论如何检查以下内容:

  • 检查您是否以相同的速度发送消息,根据您的说法,似乎您有峰值。
  • 另一种可能性是群集(生产者或消费者)中的其他kafka客户端(不一定使用相同的主题)会使这种情况发生,因为经纪人超负荷(检查经纪人cpu / network)。

为了最大限度地减少导致此保留的原因,您应该将buffer-memory增加到32MB以上,请认为32MB是默认设置,并且您将此设置为较低。您拥有的越低,缓冲区就越容易填满,如果发生这种情况,它最多会阻塞max.block.ms,请求会在request.timeout.ms之后超时。

您应该增加的另一个参数是batch-size,此参数以字节为单位,而不是消息数。还应该增加linger.ms,如果在用户请求时创建生成器消息,不要增加很多,一个好的选择可能是1-4毫秒。

batch.size已满或需要超过linger.ms时,将发送消息,以获得比batch.size更多的数据。在正常情况下,大批量会增加吞吐量,但如果延迟太低则无法提供帮助,因为在您有足够的数据来获取batch.size之前,您将发送。

还要在生产者日志上重新检查属性是否正确加载。