Skip to content

KAFKA-14468: Implement CommitRequestManager to manage the commit and autocommit requests#13021

Merged
guozhangwang merged 6 commits into
apache:trunkfrom
philipnee:consumer-refactor-commit-request-manager
Feb 24, 2023
Merged

KAFKA-14468: Implement CommitRequestManager to manage the commit and autocommit requests#13021
guozhangwang merged 6 commits into
apache:trunkfrom
philipnee:consumer-refactor-commit-request-manager

Conversation

@philipnee

@philipnee philipnee commented Dec 19, 2022

Copy link
Copy Markdown
Contributor

This pull request introduces a CommitRequestManager to efficiently manage commit requests from clients and the autocommit state. The manager utilizes a "staged" commit queue to store commit requests made by clients. A background thread regularly polls the CommitRequestManager, which then checks the queue for any outstanding commit requests. When permitted, the CommitRequestManager generates a PollResult which contains a list of UnsentRequests that are subsequently processed by the NetworkClientDelegate.

In addition, a RequestManagerRegistry has been implemented to hold all request managers, including the new CommitRequestManager and the CoordinatorRequestManager. The registry is regularly polled by a background thread in each event loop, ensuring that all request managers are kept up to date and able to handle incoming requests

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

@philipnee
philipnee force-pushed the consumer-refactor-commit-request-manager branch from 505c362 to 8b7eb65 Compare December 20, 2022 04:06
@philipnee
philipnee marked this pull request as ready for review December 20, 2022 04:08
@philipnee

Copy link
Copy Markdown
Contributor Author

@kirktrue - Could you take a quick pass?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to refactor this sad toString method.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should test the order commit when calling poll. The commit sequence order should be guarantee.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it is worth writing a builder.

@vvcephei

Copy link
Copy Markdown
Contributor

Thanks @philipnee !

I just made a quick pass. I'm sorry; I haven't been keeping up with the progress of your project, so I'm a little hazy on the details.

It looks like the new CommitRequestManager is a component that lives in the background part of the system, basically to help the background thread keep track of commit requests that have been/need to be sent to the network?

I think that makes sense, but in that case, it is mildly surprising to see autocommit living where it lives. I initially would have expected it to originate from the foreground, but on second though, maybe it's because the background thread runs on a reliable timer? The caller is required to call poll on a regular basis, but maybe it's not frequent enough for your purposes?

It would be good to understand the general principle for the division of responsibilities between the foreground and background. Do you have this documented somewhere that we can use for a north star?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should finalize the plan for subscriptionState, whether we will reuse the same class or implement a new one (and deprecate the old one)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the main problem with using the current SubscriptionState is that it couples together the commit position and the fetch position. With the move to the background thread, I don't think we can depend on these advancing in lock-step anymore. The fetch position can advance after we have received a fetch position and the commit position will be advanced when the application calls poll(). With that said, it is probably simpler to build this into the current SubscriptionState instead of creating something new.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. I checked the current SusbscriptionState class and feel it's still resuable.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the main problem with using the current SubscriptionState is that it couples together the commit position and the fetch position. With the move to the background thread, I don't think we can depend on these advancing in lock-step anymore. The fetch position can advance after we have received a fetch position and the commit position will be advanced when the application calls poll(). With that said, it is probably simpler to build this into the current SubscriptionState instead of creating something new.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this and config are unused

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can simplify this API by removing the callback argument. Instead, if we let this API return CompletableFuture as suggested in another comment, then we can chain the callback logic to the future when invoked from KafkaConsumer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use a normal CompletableFuture instead of RequestFuture. The latter is bound up with ConsumerNetworkClient which we are not using in this implementation.

Also, I'm surprised to see this return something as low level as ClientResponse. I think we can leave the response handling confined to this class and just expose CompletableFuture<Void> or something like that.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stuff like this is better to just chain on top of a future.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would this be optional? We cannot commit offsets unless we have a coordinator.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The optional is kind of annoying. I wonder if we could treat auto-commit disabled as having an auto-commit interval of Long.MaxVAlue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense to use a MaxValue as well, my counter argument is, i think explicitly disabling autoCommitState makes the logic more straightforward.

commit manager

clean up

clean up

clean up

client poll to autocommit

wip

Addressed some PR comments

Init commit for the request manager
@philipnee
philipnee force-pushed the consumer-refactor-commit-request-manager branch from 0538244 to 40abf2e Compare January 24, 2023 21:57

@guozhangwang guozhangwang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One major question is that stagedCommits queue seems not being cleared, is that intentional? All others are minor.

import java.util.Objects;
import java.util.Optional;

public class GroupStateManager {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just call it GroupState since it does not do any management, but more of a grouping of multiple primitive states?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for suggestions, changed.

private final Logger log;
private final Optional<AutoCommitState> autoCommitState;
private final CoordinatorRequestManager coordinatorRequestManager;
private final GroupStateManager groupState;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest we either change the class name to just GroupState or name this field groupStateManager? Personally I prefer the former.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. makes sense. thanks.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. I checked the current SusbscriptionState class and feel it's still resuable.


Map<TopicPartition, OffsetAndMetadata> allConsumedOffsets = subscriptionState.allConsumed();
log.debug("Auto-committing offsets {}", allConsumedOffsets);
sendAutoCommit(allConsumedOffsets);

@guozhangwang guozhangwang Feb 3, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should reset immediately or should we have a flag of autoCommitInFlight and only reset to re-enable canSendAutocommit, because I vaguely remember in the past, we have seen issues where auto commit keeps being triggered while there are still auto commits inflight due to network partition, causing OOM and other issues. And that's why we ended up adding this flag in the old code.

If we want to go very fancy, we can potentially just update the unsent auto commit request inside the stagedCommits when we want to send another..

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I see your point. Let's track the inflight status in the autocommit state and reset them upon completing the future (in the callback).

log.debug("Completed asynchronous auto-commit of offsets {}", allConsumedOffsets);
}

if (throwable instanceof RetriableCommitFailedException) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge this as else if along with line 124?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it to the exceptionally block, it think it would be clearer this way.

public NetworkClientDelegate.PollResult poll(final long currentTimeMs) {
maybeAutoCommit(currentTimeMs);

if (stagedCommits.isEmpty()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stagedCommits seems never cleared?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, addressed.

final CoordinatorRequestManager coordinatorManager) {
final GroupStateManager groupState,
final CoordinatorRequestManager coordinatorManager,
CommitRequestManager commitRequestManager) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is not final?

private boolean process(final PollApplicationEvent event) {
Optional<RequestManager> commitRequestManger = registry.get(RequestManager.Type.COMMIT);
if (!commitRequestManger.isPresent()) {
return false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why return false here? If the user did not set group.id and never use auto or manual commits, then here we should just skip right?

@guozhangwang

Copy link
Copy Markdown
Contributor

Made another look, LGTM. Leaving for @hachikuji for a final look.

@philipnee

Copy link
Copy Markdown
Contributor Author

much thanks @guozhangwang

@philipnee

Copy link
Copy Markdown
Contributor Author

There's still a couple things to be hashed out in the future, in particular

  1. how do we plan to structure the subscription state and
  2. what are the API calls for the subscription state in the background thread

For this specific PR, I think let's use the existing API, and change it later. There's really not a lot of interaction to the subscription state for this model for now, so I think it's fine. In the new model, we might need to update the commit positions in the callback, but we can add that after this.

@hachikuji @kirktrue

@guozhangwang
guozhangwang merged commit 62431dc into apache:trunk Feb 24, 2023
@philipnee philipnee added KIP-848 The Next Generation of the Consumer Rebalance Protocol ctr Consumer Threading Refactor (KIP-848) labels May 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ctr Consumer Threading Refactor (KIP-848) KIP-848 The Next Generation of the Consumer Rebalance Protocol

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants