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

A68: Random subsetting with rendezvous hashing LB policy #423

Open
wants to merge 14 commits into
base: master
Choose a base branch
from

Conversation

s-matyukevich
Copy link

@s-matyukevich s-matyukevich commented Apr 11, 2024

Replaces #383

Related to #430 which describes an LB policy that could be used in combination with random subsetting to correct the resulting server-side load imbalance.

@s-matyukevich s-matyukevich changed the title Random subsetting with rendezvous hashing LB policy A68: Random subsetting with rendezvous hashing LB policy Apr 11, 2024
A68-random-subsetting.md Outdated Show resolved Hide resolved
* When the lb policy is initialized it also creates a random 32-byte long `salt` string.
* After every resolver update the policy picks a new subset. It does this by implementing `rendezvous hashing` algorithm:
* Concatenate `salt` to each address in the list.
* For every resulting entity compute [MurmurHash3](https://en.wikipedia.org/wiki/MurmurHash) hash, which produces 128-byte output.

Choose a reason for hiding this comment

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

There is no dependency on murmur from grpc, at least in Go, as of today. You can use xxhash which is depended upon by ring_hash.

Copy link
Author

Choose a reason for hiding this comment

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

updated to use xxhash, This changes the algorithms slightly as we can use random pre-generated seed instead of concatenating salt to each address. The new version is even simpler.


* The policy receives a single configuration parameter: `subset_size`, which must be configured by the user.
* When the lb policy is initialized it also creates a random 32-byte long `salt` string.
* After every resolver update the policy picks a new subset. It does this by implementing `rendezvous hashing` algorithm:

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

Done.

A68-random-subsetting.md Outdated Show resolved Hide resolved

### Handling Parent/Resolver Updates

When the resolver updates the list of addresses, or the LB config changes, Random subsetting LB will run the subsetting algorithm, described above, to filter the endpoint list. Then it will create a new resolver state with the filtered list of the addresses and pass it to the child LB. Attributes and service config from the old resolver state will be copied to the new one.

Choose a reason for hiding this comment

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

I think you should replace addresses with endpoints to take A61 into consideration.

Copy link
Author

Choose a reason for hiding this comment

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

Done.


## Proposal

Introduce a new LB policy, `random_subsetting`. This policy selects a subset of addresses and passes them to the child LB policy. It maintains 2 important properties:

Choose a reason for hiding this comment

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

I think you need to replace addresses with endpoints to account for https://github.com/grpc/proposal/blob/master/A61-IPv4-IPv6-dualstack-backends.md, where each endpoint may have multiple addresses.

Copy link
Author

Choose a reason for hiding this comment

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

Done.

A68-random-subsetting.md Outdated Show resolved Hide resolved
* The policy receives a single configuration parameter: `subset_size`, which must be configured by the user.
* When the lb policy is initialized it also creates a random 32-byte long `salt` string.
* After every resolver update the policy picks a new subset. It does this by implementing `rendezvous hashing` algorithm:
* Concatenate `salt` to each address in the list.

Choose a reason for hiding this comment

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

You'll have to decide which address, in case the endpoint has more than one (I think you can use the first address?).

Copy link
Author

Choose a reason for hiding this comment

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

Updated the doc to use the first address.

As described in [gRFC A52](https://github.com/grpc/proposal/blob/master/A52-xds-custom-lb-policies.md), gRPC has an LB policy registry, which maintains a list of converters. Every converter translates xDS LB policy to the corresponding service config. In order to allow using the Random subsetting LB policy via xDS, the only thing that needs to be done is providing a corresponding converter function. The function implementation will be trivial as the fields in the xDS LB policy will match exactly the fields in the service config.

## Rationale
### Alternatives Considered: Deterministic subsetting

Choose a reason for hiding this comment

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

You should probably discuss the trade offs of doing this kind of subsetting in the control plane, since it was discussed in the original proposal.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, but I posted a link to the tl;dr; of the discussion, so you think this is not enough?

Choose a reason for hiding this comment

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

I'm thinking of the option of doing random subsetting in the control plane by sending different EDS responses (with different subsets) to each dataplane, or the equivalent with other resolvers. It is simple to implement with xDS and works for Envoy and gRPC. IIRC the main argument for not going that route is the need to have an xDS infrastructure (this is a big barrier for our orgs, and probably others), and existing limitations of https://github.com/envoyproxy/go-control-plane.

This was discussed in https://github.com/grpc/proposal/pull/383/files#r1308024474.

In order to understand this proposal, I think users will need to understand the trade off of doing it as a balancer in each data plane rather than directly in service discovery.

s-matyukevich and others added 6 commits April 15, 2024 08:02
Co-authored-by: Antoine Tollenaere <atollena@gmail.com>
Co-authored-by: Antoine Tollenaere <atollena@gmail.com>
Co-authored-by: Antoine Tollenaere <atollena@gmail.com>
@s-matyukevich s-matyukevich mentioned this pull request Apr 26, 2024
@s-matyukevich
Copy link
Author

Bump on this. It has been almost a month since the proposal was submitted and no one from gRPC maintainers commented on it yet. cc @markdroth and @ejona86 since you both reviewed previous version of the proposal and have full context.

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.

None yet

2 participants