Skip to content
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

balancer: support injection of per-call metadata from LB policies #5853

Merged
merged 5 commits into from Dec 20, 2022

Conversation

easwars
Copy link
Contributor

@easwars easwars commented Dec 9, 2022

Summary of changes:

  • New field added to balancer.PickResult. LB policies can use this to inject per-call arbitrary metadata.
  • Arbitrary metadata returned by LB policies is then plumbed all the way to the place where new streams are created, and these are sent out as part of the HEADERS frame.

RELEASE NOTES:

  • balancer: support injection of per-call metadata from LB policies

@easwars easwars added the Type: API Change Breaking API changes (experimental APIs only!) label Dec 9, 2022
@easwars easwars requested a review from dfawley December 9, 2022 17:42
@easwars easwars added this to the 1.52 Release milestone Dec 9, 2022
@easwars
Copy link
Contributor Author

easwars commented Dec 12, 2022

@dfawley : Based on our offline discussion, I've made changes to merge metadata from LB policies with existing call metadata instead of overwriting existing one. PTAL. Thanks.

Copy link
Member

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

LGTM modulo this one potential concern.

stream.go Outdated
// in a form passable to AppendToOutgoingContext().
md, _ := metadata.FromOutgoingContext(ctx)
md = metadata.Join(md, a.pickResult.Metatada)
ctx = metadata.NewOutgoingContext(a.ctx, md)
Copy link
Member

Choose a reason for hiding this comment

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

Should this not update a.ctx in place instead? I'm a bit worried if we ever use it again later, it will be the wrong one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • clientStream.ctx is the RPC's context (from what I can see, it is used directly and not derived from it)
  • csAttempt.ctx is derived from the above context, and is used in the following places
    • getTransport(): is passed to Pick()
    • sending/receiving messages and when the attempt is closed, the context is passed to stats handler methods

I feel that by not modifying the csAttempt's context and instead deriving a new one (with metadata added by the LB policy) to be passed to NewStream(), we can ensure that we don't have any surprises when the attempt is retried. If we modify the csAttempt's context and the attempt is retried, and we call Pick() with the modified context, the LB policy's metadata might show up multiple times in there.

Copy link
Member

Choose a reason for hiding this comment

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

Each attempt creates a new csAttempt, so that should not be a concern. Technically the attempt is not what's retried, but the RPC (clientStream).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Each attempt creates a new csAttempt, so that should not be a concern.

Oh yes, that's right.

I'm a bit worried if we ever use it again later, it will be the wrong one.

When will we ever use it again? From what I see, the context is used in getTransport() and while invoking stats handler methods. Even if we add few usages for this context, why would it be helpful to pass the extra metadata added by the LB policy?

I'm not opposed to updating the attempt's context in place with metadata from the LB policy. But, I thought it was safer to derive one from it and pass it to NewStream and continue using the existing one for everything else, since that will minimize the effect of this change.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure we ever will use it again. But if ClientStream.Context() doesn't contain the true outgoing metadata, then that could potentially be considered a bug.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

clientStream.Context() returns the context from the underlying transport stream.

if cs.attempt.s != nil {

And we use the modified context (with all outgoing metadata) when creating the transport stream. So, it looks like we are good here too.

Copy link
Member

Choose a reason for hiding this comment

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

Honestly it's still feeling wrong to not update the attempt's context when the metadata is updated by the LB policy. Unless there's a strong reason not to do this, then I'd rather do it and be safe vs. sorry. The concerns about it affecting subsequent attempts are a misunderstanding of the design of attempts (everything in an attempt should be local to that one attempt), and not a good reason to not update in place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@dfawley dfawley assigned easwars and unassigned dfawley Dec 14, 2022
@easwars easwars assigned dfawley and unassigned easwars Dec 15, 2022
@dfawley dfawley modified the milestones: 1.52 Release, 1.53 Release Dec 16, 2022
@dfawley dfawley assigned easwars and unassigned dfawley Dec 20, 2022
@easwars easwars assigned dfawley and unassigned easwars Dec 20, 2022
Copy link
Member

@dfawley dfawley left a comment

Choose a reason for hiding this comment

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

LGTM (modulo a todo comment suggestion), thanks!

stream.go Outdated
Comment on lines 469 to 470
// TODO: Make it possible to retrieve key value pairs from metadata.MD
// in a form passable to AppendToOutgoingContext().
Copy link
Member

Choose a reason for hiding this comment

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

Maybe add to this sentence: ..., or create a version of AppendToOutgoingContext that accepts a metadata.MD. ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@dfawley dfawley assigned easwars and unassigned dfawley Dec 20, 2022
@easwars easwars merged commit 68b388b into grpc:master Dec 20, 2022
1 check passed
@easwars easwars deleted the picker_api_change branch December 20, 2022 23:13
easwars added a commit to easwars/grpc-go that referenced this pull request Dec 21, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Type: API Change Breaking API changes (experimental APIs only!)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants