Spring Kafka生产者抛出TimeoutExceptions

Jod*_*iug 10 java apache-kafka spring-boot 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
Run Code Online (Sandbox Code Playgroud)

详细设置

侦听器设置为允许来自外部世界的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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

另外,我linger.ms在代码中设置为100,强制消息在100ms内传输.延迟时间设置为故意低,因为用例需要最少的延迟.

分析

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

会是什么呢?

pad*_*ilo 3

当生产者比代理更快时,通常会出现此问题,您的设置发生这种情况的原因似乎是 SSL 需要额外的 CPU,这可能会减慢代理的速度。但无论如何请检查以下内容:

  • 检查您是否以相同的速度生成消息,根据您所说的内容,您似乎遇到了峰值。
  • 另一种可能性是集群中的其他 kafka 客户端(生产者或消费者)不一定使用相同的主题,因为代理超载(检查代理 cpu/网络)而导致这种情况发生。

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

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

batch.size当已满或需要更长的时间才能linger.ms拥有比 . 多的数据时,将发送消息batch.size。在正常情况下,大批量会增加吞吐量,但如果延迟太低,则无济于事,因为您将在有足够的数据来获取batch.size.

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