Skip to content

Conversation

marek-szews
Copy link

Introduce a new LB policy, random_subsetting. This policy selects a subset of addresses and passes them to the child LB policy to correct the resulting server-side load balancing.

Copy link

linux-foundation-easycla bot commented Oct 14, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@easwars easwars self-assigned this Oct 15, 2025
@easwars easwars self-requested a review October 15, 2025 19:17
@easwars easwars added Type: Feature New features or improvements in behavior Area: xDS Includes everything xDS related, including LB policies used with xDS. Area: Resolvers/Balancers Includes LB policy & NR APIs, resolver/balancer/picker wrappers, LB policy impls and utilities. and removed Area: xDS Includes everything xDS related, including LB policies used with xDS. labels Oct 15, 2025
@easwars
Copy link
Contributor

easwars commented Oct 15, 2025

@marek-szews : Could you please get the tests to pass. Thanks.

Comment on lines +79 to +81
SubsetSize uint64 `json:"subset_size,omitempty"`

ChildPolicy *iserviceconfig.BalancerConfig `json:"child_policy,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

We generally use camelCase for the json annotations since the protobuf library uses that when marshalling protobuf messages to JSON. So, please change these to use camelCase. Thanks.

return b
}

// LBConfig is the config for the outlier detection balancer.
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment needs to be updated.

Copy link
Author

Choose a reason for hiding this comment

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

Done

}

// LBConfig is the config for the outlier detection balancer.
type LBConfig struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason for this type to be exported. I don't see a reason here. So, if there is no reason, please unexport it. The fields can remain exported since you might want that for JSON marshal/unmarshal.

Comment on lines +86 to +87
// Default top layer values.
SubsetSize: 10,
Copy link
Contributor

Choose a reason for hiding this comment

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

Where is this default value specified?

}

// if someonw needs subsetSize == 1, he should use pick_first instead
if lbCfg.SubsetSize < 2 {
Copy link
Contributor

Choose a reason for hiding this comment

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

The gRFC only says the following:

    // The value is required and must be greater than 0.

Is the condition that the size be at least 2 specified somewhere else?

return addressesSet[i].hash < addressesSet[j].hash
})

b.logger.Infof("resulting subset: %v", addressesSet[:b.cfg.SubsetSize])
Copy link
Contributor

Choose a reason for hiding this comment

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

Please guard this log line with a verbosity check of 2.


// implements the subsetting algorithm, as described in A68: https://github.com/grpc/proposal/pull/423
func (b *subsettingBalancer) prepareChildResolverState(s resolver.State) resolver.State {
addresses := s.Addresses
Copy link
Contributor

Choose a reason for hiding this comment

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

We should be using the Endpoints field in resolver.State for everything here (except for computing the hash where we use the first address inside of the endpoint).

Comment on lines +174 to +184
// Convert back to resolver.addresses
addressesSubset := make([]resolver.Address, b.cfg.SubsetSize)
for _, eh := range addressesSet[:b.cfg.SubsetSize] {
addressesSubset = append(addressesSubset, eh.addr)
}

return resolver.State{
Addresses: addressesSubset,
ServiceConfig: s.ServiceConfig,
Attributes: s.Attributes,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

All of this should deal with endpoints and not addresses.

Comment on lines +187 to +201
func (b *subsettingBalancer) ResolverError(err error) {
b.child.ResolverError(err)
}

func (b *subsettingBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
b.child.UpdateSubConnState(sc, state)
}

func (b *subsettingBalancer) Close() {
b.child.Close()
}

func (b *subsettingBalancer) ExitIdle() {
b.child.ExitIdle()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we embed the gracefulswitch.Balancer in the subsettingBalancer, and thereby get rid of all these forwarding methods?

ChildPolicy *iserviceconfig.BalancerConfig `json:"child_policy,omitempty"`
}

func (bb) ParseConfig(s json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to add unit tests for this method. Thanks.

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

Labels

Area: Resolvers/Balancers Includes LB policy & NR APIs, resolver/balancer/picker wrappers, LB policy impls and utilities. Status: Requires Reporter Clarification Type: Feature New features or improvements in behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants