记录kafka出现的问题,原因,与对应场景下的解决方案.
造成问题方式有很多种,这里只是记录遇到的或已知的,若有遗漏情况欢迎补充
由于问题很多出现在生产环境,故敏感信息已屏蔽,不影响问题介绍
文章目录
- 环境
- 问题
- 分析原因
- 参考解决思路
环境
- linux
- jdk1.8
- kafka-client 0.10.x.x
- kafka-server 0.10.x.x
问题
kafka-Client报错如下
com.mym.test.exception.MsgSendFailException: org.apache.kafka.common.errors.TimeoutException: Failed to allocate memory within the configured max blocking time 60000 ms.at com.mym.test.handler.produce.Producer10$1.onCompletion(Producer10.java:30)at org.apache.kafka.clients.producer.KafkaProducer.doSend(KafkaProducer.java:479)at org.apache.kafka.clients.producer.KafkaProducer.send(KafkaProducer.java:430)at com.mym.test.handler.produce.Producer10.add(Producer10.java:24)at com.mym.test.handler.Delivery.add(Delivery.java:154)at com.mym.test.DeliveryUtils.sendDataToDelivery(DeliveryUtils.java:66)at com.mym.test.common.Commons.sendPairDataToDelivery(Commons.java:71)at com.mym.test.handler.SDKStatHandler.run(SDKStatHandler.java:194)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.kafka.common.errors.TimeoutException: Failed to allocate memory within the configured max blocking time 60000 ms.
重点
Caused by: org.apache.kafka.common.errors.TimeoutException: Failed to allocate memory within the configured max blocking time 60000 ms.
分析原因
从报错信息可知,在配置的最大的阻塞时间内分配内存失败了。再解释下就是,由于异步发送,数据需要先放到缓冲区里,但是分配内存分配了blocking time这么长的时间还是分配失败,就报错了。
- 出此报错信息一般是因为kafka集群内部有问题 或着客户端方面原因
- 涉及几个配置项:再用这几个配置项来解释就是:当kafka-client向kafka某个分区发数据时,等了linger.ms或积累了batch.size量我就会发出去,否则就会先把数据放到buffer.memory这个大小的缓冲区里,往这个缓冲区里放失败时最多阻塞重试max.block.ms长时间,否则就抛出异常。
<!-- 发送总缓冲区大小(字节),默认值33554432 --><property name="buffer.memory" value="33554432"/><!-- 发送总缓冲区慢了之后最大阻塞时长,超过时长后将抛出异常,默认值60000 ms --><property name="max.block.ms" value="60000"/><!-- 单分区一次请求最大批次,默认值16384? --><property name="batch.size" value="32768"/><!-- 单分区一次请求最大批次等待时间,默认值0 ms? --><property name="linger.ms" value="5"/><!-- 单次请求包体最大大小,默认值1048576.不能超过服务端设置的接受包体最大值? --><property name="max.request.size" value="3145728"/>
- 可能因为某些原因或参数配置不合理,导致(用生产者消费者来说这个缓冲区的话)生产数据比消费数据快,导致总会有一个时间点爆满buffer.memory并且阻塞达到max.block.ms就报错。生产数据比消费数据快的情景有很多种,也就是实际上会有很多原因造成这个报错。(例如根本不消费数据,即缓冲区数据不会减少)
- 由于如果网络问题是好的且kafka集群ok的话,那此问题极有可能是参数设置不合理。因为如果可以往外发,但是发送失败的话,消息是会做过期处理,不会一直占着缓冲区
参考解决思路
- 一般kafka集群出了问题短时间自动恢复后,kafka-client也能感知到也能自动恢复。
- 长时间挂掉的话,kafka-client可能也死了,就需要手动干预重启kafka-clien或通过其他干预或检测手段来恢复,一般思路原理就是重建连或手动让旧kafka-client连接再次尝试链接
- 确定kafka-client与kafka-server无网络问题
- 检查参数是否设置合理
- zk上查看kafka是否有broker掉线
- 逐一检查kafka的log,看是否有报错或有效信息,一般要多看点日志,kafka集群除了点问题,如果集群够大,可能恢复也要一定时间,这短时间可能仍然无法使用
- Kafka问题(2):Batch containing 5 record(s) expired due to timeout while requesting metadata from broker也会造成此问题。因为kafka挂了,数据就发不出去,就会一直存在缓冲区,源源不断的数据加入缓冲区就会满掉报错
造成问题方式有很多种,这里只是记录遇到的或已知的,若有遗漏情况欢迎补充