一、现象
一直在消费消息:
2024-02-19T11:06:18.132199537Z 2024-02-19 19:06:18 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] DEBUG[org.apache.ibatis.logging.jdbc.BaseJdbcLogger
二、原因分析
1.查看配置:
enable-auto-commit: true
auto-commit-interval-ms: 5000
相当于offset每5秒自动提交一次
与每一秒消费消息不一致,通过查资料。可以通过手动提交offset.
配置需要修改为enable-auto-commit 为false,然后设置ack模式,从而进行手动提交维护offset。
模式分好7种:
RECORD: 每处理完一条记录后提交。
BATCH(默认): 每次poll一批数据后提交一次,频率取决于每次poll的调用频率。
TIME: 每次间隔ackTime的时间提交。
COUNT: 处理完poll的一批数据后并且距离上次提交处理的记录数超过了设置的ackCount就提交。
COUNT_TIME: TIME和COUNT中任意一条满足即提交。
MANUAL: 手动调用Acknowledgment.acknowledge()后,并且处理完poll的这批数据后提交。
MANUAL_IMMEDIATE: 手动调用Acknowledgment.acknowledge()后立即提交。
一般选择手动提交,MANUAL。则需要对监听消息的方法中,引入 Acknowledgment 对象参数,并调用 acknowledge() 方法进行手动提交。
改动代码较大,于是放弃了该种方案。
2.分析日志发现某一条消息,确实再重复消费。然后看到该消息包含数组内容由上千条。然后根据代码内容分析,发现都是循环掉的,而且业务复杂,不好拆解。
所以 只能修改设置:
fetch-max-wait-ms: 2000
当没有足够的数据(数据的大小不小于 fetch.min.bytes)返回给客户端时,服务器最大阻塞时间。
heartbeat-interval-ms: 40000
消费者协调员之间心跳的预期时间(单位是毫秒)
session-timeout-ms: 120000
会话连接超时时间,一般为心跳时间的3倍。
max-poll-interval-ms: 120000
每隔多长时间去拉取消息。合理设置预期值,尽量但间隔时间消费者处理完业务逻辑,否则就会被coordinator判定为死亡,踢出Consumer Group,进行Rebalance
max-poll-interval-records: 5
一次从拉取出来的数据条数。根据消费业务处理耗费时长合理设置,如果每次max.poll.interval.ms 设置的时间较短,可以max.poll.records设置小点儿,少拉取些,这样不会超时。
总之,尽可能在max.poll.interval.ms时间间隔内处理完max.poll.records条消息,让Coordinator认为消费Consumer还活着
三、解决方案
根据原因分析,采用了修改配置的方案:
session-timeout-ms: 120000
fetch-max-wait-ms: 2000
heartbeat-interval-ms: 40000
max-poll-interval-records: 5
问题最终得到解决