首页 文章

Spring Kafka 生产环境 者抛出TimeoutExceptions

提问于
浏览
9

Problem

我在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

Detailed setup

侦听器设置为允许来自外部世界的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,这迫使消息在100ms内传输 . 延迟时间设置为故意低,因为用例需要最少的延迟 .

Analysis

  • 当代理移动到SSL时,错误开始出现 .

  • 在服务器端,一切都按预期运行,日志中没有错误,我可以使用Kafka客户端工具手动连接到代理 .

  • 错误间歇出现:有时它每秒发送30条消息,有时它根本不发送任何消息 . 它可能像几个小时的魅力,然后只是一段时间的垃圾邮件超时 .

  • 客户端和服务器的时钟同步(UTC) .

  • 生产环境 和服务器端的CPU始终保持在20%左右 .

会是什么呢?

1 回答

  • 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 之前你会发送 .

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

相关问题