Skip to content

A119: Auto-Sharding LB Policy - #551

Open
easwars wants to merge 30 commits into
grpc:masterfrom
easwars:slicer
Open

A119: Auto-Sharding LB Policy#551
easwars wants to merge 30 commits into
grpc:masterfrom
easwars:slicer

Conversation

@easwars

@easwars easwars commented May 22, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@easwars
easwars requested review from dfawley, ejona86 and markdroth May 22, 2026 23:26
@easwars

easwars commented May 22, 2026

Copy link
Copy Markdown
Contributor Author

@markdroth @ejona86 @dfawley
FYI: There are still some sections with TBDs (mostly around load reporting and xDS integration). I will have them filled out as early as I possibly can. But I believe that there is still enough in here for reviews to begin. Thanks.

Comment thread A119-slicer-lb-policy.md Outdated
@easwars

easwars commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

I'm going to be making some structural changes to the spec based on our review today. Will ping here once it is ready for review. @markdroth @ejona86 @dfawley

@shivaspeaks @pawbhard Please expect some changes to the spec, but not wholesale changes. So, you could start looking at it from an implementation pov. Thanks.

@easwars

easwars commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

The PR is ready to be looked at.
@markdroth @ejona86 @dfawley

@markdroth markdroth left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks really good!

I have a lot of comments here, but they're mostly fine details or clarifications -- the high-level shape of this is solid, and the doc does a good job of describing it.

Please let me know if you have any questions. Thanks!

Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated

@markdroth markdroth left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is getting closer!

Please let me know if you have any questions. Thanks!

Comment thread A119-autosharding-lb-policy.md
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment on lines +332 to +335
// A timeout value for fallback to kick in when no assignments have been
// received from the sharding service.
// Defaults to 60 seconds if not specified.
google.protobuf.Duration fallback_timeout = 6;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It doesn't really matter whether it's defined here or in A121. I guess it should be in whichever of the two gRFCs is going to be merged last.

Please coordinate with @mbissa.

Comment thread A119-slicer-lb-policy.md Outdated
Comment on lines +146 to +147
allEndpointsInSlice []int // Indices into sliceMap.allEndpoints
endpointsByState [5][]int // Array indexed directly by connectivity.State (ranges 0..4)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Okay. @pawbhard, let's consider this for the C-core implementation.

Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment on lines +752 to +757
1. Parsing a `GrpcService` proto embedded within an LB policy's configuration
into its internal representation, requires access to the following:
* the complete bootstrap configuration to access the `allowed_grpc_services`
section of the bootstrap configuration.
* configuration of the specific xDS server that delivered this resource, to
determine if the server is to be trusted or not.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Meant to tag @pawbhard on this comment.

Comment thread A119-autosharding-lb-policy.md
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-autosharding-lb-policy.md
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-autosharding-lb-policy.md
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-autosharding-lb-policy.md
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
@easwars

easwars commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

@markdroth : I think I've addressed all your comments. Thanks for the detailed review.

@markdroth markdroth left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks really good! Remaining comments are mostly minor.

@ejona86 and @dfawley, please review.

Comment thread A119-autosharding-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-autosharding-lb-policy.md Outdated
Comment on lines +571 to +572
If validation fails, the LB policy must terminate the stream to the sharding
service, and attempt to re-establish it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this really the right thing to do? If we get an invalid assignment, that's likely a bug in the slicer service, and it's not clear to me that reestablishing the stream will fix it -- we'll probably just get the same bad data again after we restart the stream. But restarting the stream will cause load on the server, so I'd be worried about a cascading failure here: a bug in the slicer service could cause all of the clients to start terminating and reconnecting streams, which could cause a lot of unexpected load.

I suggest asking the slicer folks how they handle this kind of case today.

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've updated this section. PTAL. Thanks.

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.

Also, updated to include a new component named AssignmentProvider which will encapsulate all details of the interaction with the sharding service and will provide usable assignments to the LB policy.

One thing I'm still a little uncertain is whether if one of those validations fail (like one slice entry contains an invalid index), do we still use the new assignment but send an AssignmentAck with accepted set to true but with the error message populated? (I currently have it the other way around, but willing to change it).

If we do the above, then the only cases where we would end up setting the accepted field to false would be when we have no usable slices in the assignment. Is that your understanding too?

Thanks

Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-autosharding-lb-policy.md
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-slicer-lb-policy.md Outdated
Comment thread A119-autosharding-lb-policy.md Outdated
Comment thread A119-autosharding-lb-policy.md Outdated
@markdroth markdroth changed the title A119: Slicer LB Policy A119: Auto-Sharding LB Policy Aug 10, 2026

@jggj-c jggj-c left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

...

Comment thread A119-autosharding-lb-policy.md Outdated
If a new gRPC channel is created:
* Create a new `Shard` stream on the newly created gRPC channel, and,
* Close the previously created gRPC channel to the sharding service
* If the `slicing_target` field has changed, create a new `Shard` stream because

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

In this case do we discard existing and enter assignment pending ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No, we start a new initial assignment timer but keep using the previous assignment until we either get a new assignment or the timer fires. This is covered in the "Fallback at Startup" section above.

Comment thread A119-autosharding-lb-policy.md
#### Assignment

The LB policy relies on an internal helper component, which we will refer to as
the `AssignmentProvider`, to produce a validated and gap-free set of key-ranges

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider calling this AutoshardingClient instead.

Comment on lines +620 to +621
If validation fails, the `AssignmentProvider` must not send an update to the LB
policy and must send an `AssignmentAck` message with the following contents:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we get an update that is invalid, I think we should return an indication of an invalid update to the LB policy. That way, if the LB policy is waiting for the initial assignment timer, it can immediately act as if the timer has fired rather than waiting for the timeout. That way, we don't need to wait for the timer to fire before going into fallback mode or starting to fail RPCs.

Comment on lines +627 to +630
Note that gaps in the key-ranges represented by the `Slice`s are allowed. In
this case, the `AssignmentProvider` must fill these gaps with `Slice`s that
contain no endpoints. This will cause requests that match these `Slice`s to
fallback (if enabled) or fail.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't remember where we landed on this... Didn't we decide that if this happens, we should send back an AssignmentAck that sets the error_message but sets accepted to true?

I'm pretty sure there was some case where we were going to send back an error message with accepted = true, because that was the main reason we separated this into two fields.

m: dict[str, EndpointState]
```

The LB policy must create a new `EndpointMap` whenever it receives new endpoints

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should probably say something here about how we handle collisions in hostnames. I think we should just say that implementations should pick one of them, but it doesn't matter which one.

* This allows the sharding service to not resend a previously sent good
assignment in the case of a stream failure.

#### Handling responses from the Autosharding server

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we need to cover the fact that if we restart the stream and receive an update with a generation number older than the last one we previously saw, we should ignore the old update and stick with the previous assignment.

However, if the channel key changes, do we want to retain the previous generation? I think we should not, because if the channel target changed, we might be talking to a completely different autosharding service that might have a completely different generation number. If we refuse to accept an assignment with a lower generation than the one that we saw from the previous autosharding service, we may fail to accept any updates for a long time.

Note that it is also possible that the channel key will change because of initial metadata or credentials changing without actually changing the channel target, in which case we don't really need to throw away the generation number. However, those cases seem less likely in practice, and the behavior is really not that bad if we do throw away the generation number in that case: we would temporarily revert to an older assignment, but presumably the problem would fix itself fairly quickly on the next update.

Similar question when the autosharding target changes. I assume that there will be a different generation number for each target, so we probably want to throw away the previously seen generation number in that case too.

Comment on lines +716 to +719
# No assignment covers this key. This is only possible when the
# initial_assignment_timeout has expired *and* no valid assignments have
# been received from the sharding service.
if slice_idx is None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it might wind up being easier to return a separate failing picker in this case. In C-core, we have a common TransientFailurePicker class that any LB policy can return when it wants to fail all RPCs. If we do that, then we know that the slice map lookup here must always return a valid result, because we won't be using this picker in any case where it wouldn't.

I'm not sure if Java and Go have an equivalent of the TransientFailurePicker or not. If not, it's fine to leave this as-is -- maybe just add a note that implementations can choose to use a different picker for this case.

CC @pawbhard


def pick(self, pick_args: PickArgs) -> PickResult:
# Extract sharding key from request metadata/header
key = extract_key_from_metadata(pick_args, self.lb_config.key_header_name)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If this lookup fails (i.e., if the RPC does not have the specified header), we should fail the pick.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants