[ 
https://issues.apache.org/jira/browse/KAFKA-20995?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Eric Chang updated KAFKA-20995:
-------------------------------
    Description: 
h2. Status

*Draft for discussion.* Implementation acceptance remains pending.

KIP: 
[KIP-1371|https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=449282795]
Discussion thread: TBD

h2. Summary

Consumer request managers currently return outgoing requests together with one 
numeric wait. Several busy-loop fixes share the same failure shape: a timer 
reaches zero while an in-flight request, unavailable coordinator, or another 
prerequisite prevents the related work from progressing. The zero duration 
immediately starts another iteration. Existing fixes repair each path with 
local guards or substitute another configured timeout, leaving the same 
relationship to be reconstructed for every manager state.

KIP-1371 introduces an internal {{ManagerPollCondition}} vocabulary. Each 
request-manager {{poll()}} returns its work and the condition for the next 
manager pass:

* {{ready()}}: another local step can run immediately.
* {{after(now, delayMs)}}: re-evaluate at the retained absolute deadline.
* {{idle()}}: this work source has no autonomous deadline.
* {{either(first, second)}}: retain the earlier of independent obligations.

The request owner evaluates eligibility before configuration-derived timing. 
Request admission and scheduling use the same owner-local decision, while 
independent operation and transport deadlines remain visible. The network 
thread polls every manager once, aggregates the returned conditions, and bounds 
network I/O by the earliest manager or transport deadline.

h2. Evidence

* [KAFKA-20253 / PR #22836|https://github.com/apache/kafka/pull/22836] 
demonstrates an in-flight coordinator request whose elapsed retry timer 
repeatedly requested immediate network polling.
* [KAFKA-21031 / PR #23357|https://github.com/apache/kafka/pull/23357] 
demonstrates the same network-scheduling shape for an in-flight heartbeat with 
an expired heartbeat timer.
* [KAFKA-20970 / PR #23227|https://github.com/apache/kafka/pull/23227] and 
[KAFKA-21010 / PR #23348|https://github.com/apache/kafka/pull/23348] show the 
related timeout-substitution hazard in the separate application-wait projection.

These issues have path-specific fixes or proposed fixes. The KIP addresses the 
recurring programming model so the prerequisite and retained deadlines can be 
reviewed together.

h2. Scope

The proposal covers the async consumer request-manager loop used by regular, 
share, and Streams consumers. It changes internal scheduling types and the 
internal per-manager application-wait projection. Public consumer APIs, 
configuration, metrics, wire protocols, thread topology, manager order, and 
input wakeups remain unchanged.

Transport contributes its earliest unsent or sent request timeout whenever a 
manager returns {{idle()}}, so removing a manager deadline cannot suppress 
request expiration. Performance is an acceptance constraint; current 
measurements do not establish general idle CPU savings or throughput 
non-regression.

h2. Validation

The prototype migrates coordinator, commit, topic metadata, share 
acknowledgement, Streams topology, and regular/share heartbeat scheduling to 
shared owner-local decisions. Focused tests cover retry, in-flight, timeout, 
throttle, leave, close, and independent-expiry behavior. Before merge, 
validation must complete the transport-deadline integration, 
zero/positive/maximum timer sweep, loop-level liveness coverage, and stable 
performance comparison.


  was:
h2. Status

*Draft for discussion.* This issue records the narrowed scheduling proposal for 
KIP-1371. Implementation acceptance remains pending.

KIP: 
[KIP-1371|https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=449282795]
Discussion thread: TBD

The linked Confluence page still contains the earlier, broader proposal and has 
not yet been synchronized with the scope described here.

h2. Summary

The consumer network thread currently invokes each request manager to perform 
work and obtain a delay for the next network poll. An expired timer may return 
zero even when a response or another prerequisite is still needed before work 
can proceed. Authors must account for this relationship in each manager; 
missing it can cause polling without useful progress.

This proposal introduces a programming model that expresses wait conditions 
separately from executing work. Each manager declares whether it can run now, 
must wait until a retained deadline, or needs an input that changes its state. 
The loop applies that declaration before invoking the manager. The goal is to 
make wait conditions easier to express, review, compose, and test, reducing the 
risk of busy loops.

The change retains deadline-driven network polling, the ordered manager scan, 
existing threads and input wakeups. Managers retain ownership of their state 
and domain policy. Performance is an acceptance constraint and a possible 
benefit, not the primary justification.

h2. Existing evidence

* [KAFKA-20253: High CPU loop on consumer after failed 
re-authentication|https://issues.apache.org/jira/browse/KAFKA-20253] — the 
merged [PR #22836|https://github.com/apache/kafka/pull/22836] changes 
coordinator discovery to return {{PollResult.EMPTY}} while a request is in 
flight, instead of letting expired backoff request immediate network polling. 
This directly demonstrates the timer/prerequisite mismatch.
* [KAFKA-20426: Using both group.id and assign() causes a busy loop in 
AsyncKafkaConsumer|https://issues.apache.org/jira/browse/KAFKA-20426] and 
[KAFKA-20970: Another busy loop happens if auto.commit.interval.ms is less than 
bootstrap.resolve.timeout.ms|https://issues.apache.org/jira/browse/KAFKA-20970] 
have merged fixes in [PR #22018|https://github.com/apache/kafka/pull/22018] and 
[PR #23227|https://github.com/apache/kafka/pull/23227]. They illustrate related 
prerequisite checks in application-wait calculations. Those application-wait 
changes are supporting evidence, not fixes delivered by this proposal.

These cases are already fixed. The proposal addresses the recurring programming 
pattern rather than claiming to fix those bugs again. The existing interface 
permits correct implementations; the improvement is an explicit scheduling 
boundary that consistently applies the conditions reported by managers.

h2. Proposed changes

Introduce an internal {{nextPollCondition(long currentTimeMs)}} query, separate 
from {{poll(long currentTimeMs)}}:

* {{ready()}}: a local step can be attempted now, whether or not it produces a 
network request.
* {{after(now, delayMs)}}: recheck at a deadline derived from retained owner 
state. Repeated queries must not postpone it.
* {{idle()}}: no autonomous step is due; an existing input path must change 
state before further work is eligible.

The query does not produce requests, complete futures, or advance domain state. 
{{poll()}} retains state changes and request production. Once migration is 
complete, {{PollResult}} carries outgoing requests without 
{{timeUntilNextPollMs}}.

{{either(first, second)}} combines independent conditions; it is not a fourth 
form. For example, a metadata request waiting for a response may retain its 
operation-expiry deadline while a separate request retains its retry deadline. 
The combined condition is ready when either is ready and keeps the shorter wait.

Before each manager's turn, the loop queries its condition and invokes it only 
when eligible. After the ordered pass, the loop re-queries conditions to 
observe newly enabled work and bound the network wait, retaining the existing 
maximum poll interval. One manager's urgency does not make every manager 
eligible.

For coordinator discovery already in flight, {{idle()}} removes unnecessary 
manager invocation while the network client continues processing the response 
and transport timeout. If the manager owns an independent operation deadline, 
that deadline must still be represented.

h2. Scope

This proposal covers request-manager scheduling on {{ConsumerNetworkThread}}, 
including the consumer, share consumer, and Streams paths using that loop.

It preserves public APIs, configuration, metrics, wire protocols, thread 
topology, and the {{ConsumerNetworkThread}} name. The separate duration-based 
{{maximumTimeToWait()}} interface and application-wait publication remain 
unchanged. Shutdown {{pollOnClose()}} remains unconditional.

Cross-manager state ownership, completion/publication ordering, lifecycle 
trackers, general retry or recovery policies, and application-thread wakeup 
policy are outside this proposal. The earlier reactor and lifecycle POC is not 
the implementation scope of this issue.

h2. Validation and open questions

* Verify deadlines, enabling inputs, request ordering, and shutdown behavior 
across managers. Owner-level mixed retry/expiry tests provide focused evidence, 
but do not replace loop-level or broker-backed validation.
* Resolve migration compatibility for non-urgent invocation opportunities, 
particularly Streams reconciliation. The experimental {{onLoop}} option is not 
an adopted fourth form, and complete coverage by the three core forms is not 
yet established.
* Establish performance without material regression. Current measurements do 
not establish general idle CPU savings or throughput non-regression. Allocation 
representation remains an implementation question.

The mechanism applies declared conditions; it does not infer correct domain 
policy. Incorrectly returning {{ready()}} can still cause a busy loop, and 
omitting an expiry from {{idle()}} can delay completion. State-transition tests 
remain necessary.


        Summary: KIP-1371: Explicit Wait Conditions for Consumer Request 
Managers  (was: KIP-1371: Condition-Driven Consumer Request Manager Scheduling)

> KIP-1371: Explicit Wait Conditions for Consumer Request Managers
> ----------------------------------------------------------------
>
>                 Key: KAFKA-20995
>                 URL: https://issues.apache.org/jira/browse/KAFKA-20995
>             Project: Kafka
>          Issue Type: Improvement
>          Components: consumer
>            Reporter: Eric Chang
>            Assignee: Eric Chang
>            Priority: Major
>
> h2. Status
> *Draft for discussion.* Implementation acceptance remains pending.
> KIP: 
> [KIP-1371|https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=449282795]
> Discussion thread: TBD
> h2. Summary
> Consumer request managers currently return outgoing requests together with 
> one numeric wait. Several busy-loop fixes share the same failure shape: a 
> timer reaches zero while an in-flight request, unavailable coordinator, or 
> another prerequisite prevents the related work from progressing. The zero 
> duration immediately starts another iteration. Existing fixes repair each 
> path with local guards or substitute another configured timeout, leaving the 
> same relationship to be reconstructed for every manager state.
> KIP-1371 introduces an internal {{ManagerPollCondition}} vocabulary. Each 
> request-manager {{poll()}} returns its work and the condition for the next 
> manager pass:
> * {{ready()}}: another local step can run immediately.
> * {{after(now, delayMs)}}: re-evaluate at the retained absolute deadline.
> * {{idle()}}: this work source has no autonomous deadline.
> * {{either(first, second)}}: retain the earlier of independent obligations.
> The request owner evaluates eligibility before configuration-derived timing. 
> Request admission and scheduling use the same owner-local decision, while 
> independent operation and transport deadlines remain visible. The network 
> thread polls every manager once, aggregates the returned conditions, and 
> bounds network I/O by the earliest manager or transport deadline.
> h2. Evidence
> * [KAFKA-20253 / PR #22836|https://github.com/apache/kafka/pull/22836] 
> demonstrates an in-flight coordinator request whose elapsed retry timer 
> repeatedly requested immediate network polling.
> * [KAFKA-21031 / PR #23357|https://github.com/apache/kafka/pull/23357] 
> demonstrates the same network-scheduling shape for an in-flight heartbeat 
> with an expired heartbeat timer.
> * [KAFKA-20970 / PR #23227|https://github.com/apache/kafka/pull/23227] and 
> [KAFKA-21010 / PR #23348|https://github.com/apache/kafka/pull/23348] show the 
> related timeout-substitution hazard in the separate application-wait 
> projection.
> These issues have path-specific fixes or proposed fixes. The KIP addresses 
> the recurring programming model so the prerequisite and retained deadlines 
> can be reviewed together.
> h2. Scope
> The proposal covers the async consumer request-manager loop used by regular, 
> share, and Streams consumers. It changes internal scheduling types and the 
> internal per-manager application-wait projection. Public consumer APIs, 
> configuration, metrics, wire protocols, thread topology, manager order, and 
> input wakeups remain unchanged.
> Transport contributes its earliest unsent or sent request timeout whenever a 
> manager returns {{idle()}}, so removing a manager deadline cannot suppress 
> request expiration. Performance is an acceptance constraint; current 
> measurements do not establish general idle CPU savings or throughput 
> non-regression.
> h2. Validation
> The prototype migrates coordinator, commit, topic metadata, share 
> acknowledgement, Streams topology, and regular/share heartbeat scheduling to 
> shared owner-local decisions. Focused tests cover retry, in-flight, timeout, 
> throttle, leave, close, and independent-expiry behavior. Before merge, 
> validation must complete the transport-deadline integration, 
> zero/positive/maximum timer sweep, loop-level liveness coverage, and stable 
> performance comparison.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to