Kafka consumer group rebalancing behavior when max.poll.interval.ms times out during cancellation
0 reputation · 19 May 2024, 06:45 UTC
0 reputation · 19 May 2024, 06:45 UTC
Apache Kafka consumers have built-in mechanisms for graceful shutdown through the consumer.wakeup() method, which throws WakeupException to interrupt the poll loop. However, the interaction between cancellation handling and rebalance timeouts requires careful consideration.
The max.poll.interval.ms configuration (defaulting to 7 minutes) defines the maximum time between consecutive poll() calls before the consumer triggers a rebalance. During application shutdown or cancellation scenarios, if the processing time exceeds this threshold, the consumer may leave the group unexpectedly.
Current documentation indicates that consumer.wakeup() provides a clean interruption mechanism, but the precise behavior when a wakeup occurs near or after the poll interval timeout is not clearly specified. The coordination between explicit wakeup calls, automatic timeout detection, and the resulting rebalance events needs clarification.
35275 reputation · 19 May 2024, 15:41 UTC
If max.poll.interval.ms elapses while a shutdown/wakeup is in progress, the Kafka consumer is marked dead by the coordinator and a group rebalance is triggered before the application can finish processing the WakeupException. The exception may still be thrown on the next poll(), but the consumer has already left the group.
The coordinator tracks the time between successive poll() calls. When the interval exceeds max.poll.interval.ms, it assumes the instance has crashed and sends a LeaveGroup request, initiating a rebalance. This check runs independently of the client thread, so a concurrent consumer.wakeup() cannot prevent the timeout once the timer has fired.
WakeupException is thrown only when poll() is called after consumer.wakeup() has been invoked.session.timeout.ms) and heartbeat mechanism are separate; max.poll.interval.ms guards against processing stalls, not network failures.wakeup() is called before the interval expires, the next poll() returns the exception, allowing the application to break the loop and close the consumer cleanly, thus avoiding a rebalance.wakeup() occurs after the interval has already elapsed, the consumer has already been removed; the exception is still delivered but the rebalance has proceeded.max.poll.interval.ms to a value safely above that estimate (e.g., 2× the expected maximum).consumer.wakeup() from another thread.WakeupException, break the loop, and then call consumer.close().If you observe rebalances despite these steps, check the consumer’s heartbeat latency or any prolonged blocking calls that may be preventing the poll loop from advancing.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 19 May 2024, 09:35 UTC
A consumer.wakeup() call only flags the next poll() to throw WakeupException; it does not restart or extend the max.poll.interval.ms timer. The timer starts when the previous poll() returns, so long-running work after that return can still cause the coordinator to trigger a rebalance before the application reaches the wakeup path.
For predictable cancellation in Kafka 2.0+ clients, call wakeup(), then immediately invoke poll(Duration.ZERO) within the same interval, catch WakeupException, and run a controlled leaveGroup() before closing the consumer. Verify by skipping the next poll after wakeup in a test group and checking whether the leave request comes from the client or the coordinator.