-
Notifications
You must be signed in to change notification settings - Fork 12k
Description
BUG REPORT
-
Please describe the issue you observed:
DefaultMQPushConsumer使用并发消费模式,当listener一直没有返回某条消息的消费状态,后续消息正常不断地消费成功,此时队列实际消费完成的offset不断增大,而msgTreeMap的firstKey一直停留在没有返回消费状态的消息的offset位置上,实际消费的跨度超过了设定的消息跨度流控的阈值,但会出现没有流控,队列上新消息一直在被该实例持续消费。 -
Please tell us about your environment:
-
Other information (e.g. detailed explanation, logs, related issues, suggestions how to fix, etc):
消息跨度以ProcessQueue.msgTreeMap的lastKey-firstKey计算,所得到的结果为本地缓存的未消费完的消息跨度。在某些场景下,这样计算的结果与实际这个队列消费的消息跨度不一致。
例如:
a.消费者在处理某一条消息时卡住,迟迟没有ACK,后续的消息消费又足够快,在每次拉消息判断消息跨度流控时,msgTreeMap中只有一条消息,此时getMaxSpan()得到的结果为0,不会流控;
b.消费过程中有多条消息没有ACK,这些消息的跨度(假设为N)小于跨度流控的阈值,后续消息正常在消费,这种情况下getMaxSpan()得到结果为N,也不会流控;
上述场景带来的问题是,在触发负载均衡之后,若该队列转让给其他实例消费,则新实例会重复消费。例如,firstKey为10,但实际已经消费成功了11到10000的消息,则offset在10到10000的消息在负载均衡之后会被重复消费一次。
消息跨度的流控以实际消费的跨度为准会更合理,客户端本地缓存的消息跨度肯定不大于实际消费的跨度;从控制本地缓存消息量的角度看,消息条数的流控已经能够达到目的。