Skip to content

Remove first FlowControlHandler from HTTP pipeline #128099

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

DaveCTurner
Copy link
Contributor

Today we have a FlowControlHandler near the top of the Netty HTTP
pipeline in order to hold back a request body while validating the
request headers. This is inefficient since once we've validated the
headers we can handle the body chunks as fast as they arrive, needing no
more flow control. Moreover today we always fork the validation
completion back onto the event loop, forcing any available chunks to be
buffered in the FlowControlHandler.

This commit moves the flow-control mechanism into
Netty4HttpHeaderValidator itself so that we can bypass it on validated
message bodies. Morever in the (common) case that validation completes
immediately, e.g. because the credentials are available in cache, then
with this commit we skip the flow-control-related buffering entirely.

Today we have a `FlowControlHandler` near the top of the Netty HTTP
pipeline in order to hold back a request body while validating the
request headers. This is inefficient since once we've validated the
headers we can handle the body chunks as fast as they arrive, needing no
more flow control. Moreover today we always fork the validation
completion back onto the event loop, forcing any available chunks to be
buffered in the `FlowControlHandler`.

This commit moves the flow-control mechanism into
`Netty4HttpHeaderValidator` itself so that we can bypass it on validated
message bodies. Morever in the (common) case that validation completes
immediately, e.g. because the credentials are available in cache, then
with this commit we skip the flow-control-related buffering entirely.
@DaveCTurner DaveCTurner requested a review from mhl-b May 16, 2025 14:30
@DaveCTurner DaveCTurner added >enhancement :Distributed Coordination/Network Http and internode communication implementations v9.1.0 labels May 16, 2025
@elasticsearchmachine elasticsearchmachine added the Team:Distributed Coordination Meta label for Distributed Coordination team label May 16, 2025
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-distributed-coordination (Team:Distributed Coordination)

@elasticsearchmachine
Copy link
Collaborator

Hi @DaveCTurner, I've created a changelog YAML for you.

@DaveCTurner
Copy link
Contributor Author

DaveCTurner commented May 16, 2025

NB this is not a must-have, it just seems like a decent improvement. If you think it's worth pursuing then I'd be inclined to strengthen Netty4HttpHeaderValidatorTests since there's some branches this suite doesn't cover today.

Comment on lines +87 to +91
} else {
assert message instanceof HttpContent;
assert state == State.PASSING : state; // DROPPING releases any buffered chunks up-front
ctx.fireChannelRead(message);
ctx.fireChannelReadComplete(); // downstream will have to call read() again when it's ready
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we don't care about individual chunks and in spirit of PR to process more efficiently we can compose all buffered chunks into one if there is more than one chunk.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I did play around with that idea at first but I couldn't find a totally obvious way to combine the chunks back together (it's more than just the bytes in the request body, there's also decoder errors, and the last chunk is special, and maybe some other things too). Moreover this doesn't do anything to the hot path where we complete validation inline and then stream chunks straight through anyway, so it didn't seem worth pursuing. Maybe in a follow-up?

Copy link
Contributor

Choose a reason for hiding this comment

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

Make sense. Added complexity seems unnecessary. Thanks.

Copy link
Contributor

@mhl-b mhl-b left a comment

Choose a reason for hiding this comment

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

LGTM

@DaveCTurner DaveCTurner added auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) and removed auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) labels May 19, 2025
@DaveCTurner DaveCTurner added the auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) label May 19, 2025
@DaveCTurner
Copy link
Contributor Author

Thanks Mikhail, I added some more tests (no production changes since your LGTM tho)

@DaveCTurner DaveCTurner removed the auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) label May 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Distributed Coordination/Network Http and internode communication implementations >enhancement Team:Distributed Coordination Meta label for Distributed Coordination team v9.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants