Advanced utilities for gRPC Java providing load balancing, TLS management, and server utilities
—
Advanced load balancing implementations that provide sophisticated traffic distribution, graceful policy switching, outlier detection, and multi-child load balancer patterns for gRPC services.
The GracefulSwitchLoadBalancer provides seamless switching between different load balancing policies without dropping connections.
/**
* Load balancer that gracefully swaps to a new load balancing policy.
* Maintains connections during policy transitions by keeping the old policy
* active until the new policy is ready.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/5999")
@NotThreadSafe
public final class GracefulSwitchLoadBalancer extends ForwardingLoadBalancer {
/**
* Creates a new graceful switch load balancer
* @param helper the load balancer helper for creating subchannels and updating state
*/
public GracefulSwitchLoadBalancer(Helper helper);
/**
* Handles resolved addresses and potentially switches to a new load balancing policy
* @param resolvedAddresses the resolved addresses containing policy configuration
*/
@Override
public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses);
/**
* Accepts resolved addresses and returns status
* @param resolvedAddresses the resolved addresses containing policy configuration
* @return Status indicating success or failure
*/
@Override
public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses);
/**
* Shuts down both current and pending load balancers
*/
@Override
public void shutdown();
/**
* Gets the simple class name of the current delegate load balancer
* @return delegate type name for debugging
*/
public String delegateType();
/**
* Parses load balancing policy configuration from JSON
* @param loadBalancingConfigs list of load balancing configuration maps
* @return ConfigOrError containing parsed configuration or error
*/
public static ConfigOrError parseLoadBalancingPolicyConfig(List<Map<String, ?>> loadBalancingConfigs);
/**
* Parses load balancing policy configuration with custom registry
* @param loadBalancingConfigs list of load balancing configuration maps
* @param lbRegistry the load balancer registry to use for parsing
* @return ConfigOrError containing parsed configuration or error
*/
public static ConfigOrError parseLoadBalancingPolicyConfig(List<Map<String, ?>> loadBalancingConfigs, LoadBalancerRegistry lbRegistry);
/**
* Creates load balancing policy configuration directly
* @param childFactory the child load balancer factory
* @param childConfig the child load balancer configuration (may be null)
* @return configuration object for the graceful switch load balancer
*/
public static Object createLoadBalancingPolicyConfig(LoadBalancer.Factory childFactory, @Nullable Object childConfig);
}Configuration:
/**
* Configuration for graceful switch load balancer
*/
static final class Config {
final LoadBalancer.Factory childFactory;
@Nullable final Object childConfig;
public Config(LoadBalancer.Factory childFactory, @Nullable Object childConfig);
}Usage Examples:
import io.grpc.util.GracefulSwitchLoadBalancer;
import io.grpc.LoadBalancer;
import io.grpc.LoadBalancerRegistry;
// Create graceful switch load balancer
LoadBalancer.Helper helper = createHelper(); // Your helper implementation
GracefulSwitchLoadBalancer loadBalancer = new GracefulSwitchLoadBalancer(helper);
// Parse configuration from service config
List<Map<String, ?>> lbConfigs = Arrays.asList(
Map.of("round_robin", Map.of())
);
ConfigOrError configResult = GracefulSwitchLoadBalancer.parseLoadBalancingPolicyConfig(lbConfigs);
if (configResult.getError() == null) {
Object config = configResult.getConfig();
// Use config in resolved addresses
}
// Create configuration directly
LoadBalancer.Factory roundRobinFactory = LoadBalancerRegistry.getDefaultRegistry()
.getProvider("round_robin").newLoadBalancer(helper);
Object config = GracefulSwitchLoadBalancer.createLoadBalancingPolicyConfig(roundRobinFactory, null);Base class for implementing load balancers that manage multiple child load balancers.
/**
* Base class for load balancers that manage multiple child load balancers.
* Provides infrastructure for creating and managing child balancers with
* automatic state aggregation.
*/
@Internal
public abstract class MultiChildLoadBalancer extends LoadBalancer {
/**
* Creates a new multi-child load balancer
* @param helper the load balancer helper
*/
protected MultiChildLoadBalancer(Helper helper);
/**
* Updates the overall balancing state based on child states.
* Subclasses must implement this to define how child states are aggregated
* into the overall connectivity state and picker.
*/
protected abstract void updateOverallBalancingState();
/**
* Creates a mapping from keys to resolved addresses for child load balancers
* @param resolvedAddresses the resolved addresses from name resolution
* @return map of child keys to their respective resolved addresses
*/
protected Map<Object, ResolvedAddresses> createChildAddressesMap(ResolvedAddresses resolvedAddresses);
/**
* Creates a new child load balancer state
* @param key the unique key for this child
* @return new ChildLbState instance
*/
protected ChildLbState createChildLbState(Object key);
/**
* Aggregates connectivity states using standard gRPC rules
* @param overallState the current overall state
* @param childState the child state to aggregate
* @return the new aggregated state
*/
protected static ConnectivityState aggregateState(ConnectivityState overallState, ConnectivityState childState);
/**
* Gets the load balancer helper
* @return the helper instance
*/
protected Helper getHelper();
/**
* Gets the list of children in READY state
* @return list of ready child load balancer states
*/
protected List<ChildLbState> getReadyChildren();
/**
* Accepts resolved addresses and updates child load balancers
* @param resolvedAddresses the resolved addresses
* @return Status indicating success or failure
*/
@Override
public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses);
/**
* Handles name resolution errors by forwarding to all children
* @param error the name resolution error
*/
@Override
public void handleNameResolutionError(Status error);
/**
* Shuts down all child load balancers
*/
@Override
public void shutdown();
/**
* Gets all child load balancer states for testing
* @return collection of child states
*/
@VisibleForTesting
public Collection<ChildLbState> getChildLbStates();
}Child Load Balancer State:
/**
* Represents the state of a child load balancer
*/
public class ChildLbState {
/**
* Creates a new child load balancer state
* @param key unique key for this child
* @param policyFactory factory for creating the child load balancer
*/
public ChildLbState(Object key, LoadBalancer.Factory policyFactory);
/**
* Gets the unique key for this child
* @return the child key
*/
public Object getKey();
/**
* Gets the child load balancer instance for testing
* @return the load balancer instance
*/
@VisibleForTesting
public LoadBalancer getLb();
/**
* Gets the current picker for testing
* @return the current subchannel picker
*/
@VisibleForTesting
public SubchannelPicker getCurrentPicker();
/**
* Gets the current connectivity state
* @return the current connectivity state
*/
public ConnectivityState getCurrentState();
/**
* Shuts down this child load balancer
*/
protected void shutdown();
/**
* Creates the helper for this child load balancer
* @return child-specific helper instance
*/
protected LoadBalancer.Helper createChildHelper();
/**
* Sets the current connectivity state
* @param currentState the new connectivity state
*/
protected void setCurrentState(ConnectivityState currentState);
/**
* Sets the current subchannel picker
* @param currentPicker the new picker
*/
protected void setCurrentPicker(SubchannelPicker currentPicker);
}Round-robin load balancer implementation that distributes requests evenly across available endpoints.
/**
* Load balancer that distributes requests in round-robin fashion across
* all available subchannels.
*/
final class RoundRobinLoadBalancer extends MultiChildLoadBalancer {
/**
* Creates a new round-robin load balancer
* @param helper the load balancer helper
*/
public RoundRobinLoadBalancer(Helper helper);
/**
* Updates the overall balancing state with round-robin picker
*/
@Override
protected void updateOverallBalancingState();
/**
* Creates child load balancer state for round-robin
* @param key the child key
* @return new child state
*/
@Override
protected ChildLbState createChildLbState(Object key);
}Round Robin Picker:
/**
* Picker that selects subchannels in round-robin fashion
*/
@VisibleForTesting
public static final class ReadyPicker extends SubchannelPicker {
/**
* Creates a new round-robin picker
* @param list list of subchannel pickers to rotate through
* @param index atomic integer for tracking current position
*/
public ReadyPicker(List<SubchannelPicker> list, AtomicInteger index);
/**
* Picks a subchannel using round-robin algorithm
* @param args pick arguments
* @return pick result with selected subchannel
*/
@Override
public PickResult pickSubchannel(PickSubchannelArgs args);
/**
* Gets the list of subchannel pickers for testing
* @return list of pickers
*/
@VisibleForTesting
List<SubchannelPicker> getSubchannelPickers();
}Load balancer with outlier detection and ejection capabilities for improved fault tolerance.
/**
* Load balancer that performs outlier detection and temporarily ejects
* poorly performing endpoints from the load balancing pool.
*/
@Internal
public final class OutlierDetectionLoadBalancer extends LoadBalancer {
/**
* Creates a new outlier detection load balancer
* @param helper the load balancer helper
* @param timeProvider provider for current time (for testing)
*/
public OutlierDetectionLoadBalancer(Helper helper, TimeProvider timeProvider);
/**
* Accepts resolved addresses with outlier detection configuration
* @param resolvedAddresses resolved addresses with configuration
* @return Status indicating success or failure
*/
@Override
public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses);
/**
* Handles name resolution errors
* @param error the name resolution error
*/
@Override
public void handleNameResolutionError(Status error);
/**
* Shuts down the outlier detection load balancer
*/
@Override
public void shutdown();
}Outlier Detection Configuration:
/**
* Configuration for outlier detection load balancer
*/
public static class OutlierDetectionLoadBalancerConfig {
/**
* Builder for outlier detection configuration
*/
public static class Builder {
/**
* Sets the interval between outlier detection runs
* @param intervalNanos interval in nanoseconds
* @return builder for method chaining
*/
public Builder setIntervalNanos(Long intervalNanos);
/**
* Sets the base ejection time for outliers
* @param baseEjectionTimeNanos base ejection time in nanoseconds
* @return builder for method chaining
*/
public Builder setBaseEjectionTimeNanos(Long baseEjectionTimeNanos);
/**
* Sets the maximum ejection time for outliers
* @param maxEjectionTimeNanos maximum ejection time in nanoseconds
* @return builder for method chaining
*/
public Builder setMaxEjectionTimeNanos(Long maxEjectionTimeNanos);
/**
* Sets the maximum percentage of endpoints that can be ejected
* @param maxEjectionPercent maximum ejection percentage (0-100)
* @return builder for method chaining
*/
public Builder setMaxEjectionPercent(Integer maxEjectionPercent);
/**
* Sets success rate ejection configuration
* @param successRateEjection success rate ejection settings
* @return builder for method chaining
*/
public Builder setSuccessRateEjection(SuccessRateEjection successRateEjection);
/**
* Sets failure percentage ejection configuration
* @param failurePercentageEjection failure percentage ejection settings
* @return builder for method chaining
*/
public Builder setFailurePercentageEjection(FailurePercentageEjection failurePercentageEjection);
/**
* Sets the child load balancer configuration
* @param childConfig child load balancer configuration
* @return builder for method chaining
*/
public Builder setChildConfig(Object childConfig);
/**
* Builds the outlier detection configuration
* @return configured OutlierDetectionLoadBalancerConfig
*/
public OutlierDetectionLoadBalancerConfig build();
}
}Success Rate Ejection:
/**
* Configuration for success rate based outlier ejection
*/
public static class SuccessRateEjection {
/**
* Builder for success rate ejection configuration
*/
public static class Builder {
/**
* Sets the standard deviation factor for success rate ejection
* @param stdevFactor standard deviation factor
* @return builder for method chaining
*/
public Builder setStdevFactor(Integer stdevFactor);
/**
* Sets the enforcement percentage for success rate ejection
* @param enforcementPercentage enforcement percentage (0-100)
* @return builder for method chaining
*/
public Builder setEnforcementPercentage(Integer enforcementPercentage);
/**
* Sets the minimum number of hosts required for ejection
* @param minimumHosts minimum number of hosts
* @return builder for method chaining
*/
public Builder setMinimumHosts(Integer minimumHosts);
/**
* Sets the minimum request volume required for ejection
* @param requestVolume minimum request volume
* @return builder for method chaining
*/
public Builder setRequestVolume(Integer requestVolume);
/**
* Builds the success rate ejection configuration
* @return configured SuccessRateEjection
*/
public SuccessRateEjection build();
}
}Usage Examples:
import io.grpc.util.MultiChildLoadBalancer;
import io.grpc.util.RoundRobinLoadBalancer;
import io.grpc.util.OutlierDetectionLoadBalancer;
// Custom multi-child load balancer
public class CustomLoadBalancer extends MultiChildLoadBalancer {
public CustomLoadBalancer(Helper helper) {
super(helper);
}
@Override
protected void updateOverallBalancingState() {
List<ChildLbState> readyChildren = getReadyChildren();
if (readyChildren.isEmpty()) {
getHelper().updateBalancingState(
ConnectivityState.TRANSIENT_FAILURE,
new FixedResultPicker(PickResult.withNoResult())
);
} else {
// Custom picking logic
getHelper().updateBalancingState(
ConnectivityState.READY,
new CustomPicker(readyChildren)
);
}
}
}
// Round-robin load balancer usage
LoadBalancer.Helper helper = createHelper();
RoundRobinLoadBalancer rrLoadBalancer = new RoundRobinLoadBalancer(helper);
// Outlier detection configuration
OutlierDetectionLoadBalancer.OutlierDetectionLoadBalancerConfig config =
new OutlierDetectionLoadBalancer.OutlierDetectionLoadBalancerConfig.Builder()
.setIntervalNanos(Duration.ofSeconds(10).toNanos())
.setBaseEjectionTimeNanos(Duration.ofSeconds(30).toNanos())
.setMaxEjectionPercent(50)
.setSuccessRateEjection(
new OutlierDetectionLoadBalancer.SuccessRateEjection.Builder()
.setStdevFactor(1900) // 1.9 standard deviations
.setEnforcementPercentage(100)
.setMinimumHosts(5)
.setRequestVolume(100)
.build()
)
.build();Provider implementation for registering load balancers with the gRPC registry.
/**
* Provider for outlier detection load balancer
*/
@Internal
public final class OutlierDetectionLoadBalancerProvider extends LoadBalancerProvider {
/**
* Creates a new outlier detection load balancer
* @param helper the load balancer helper
* @return new OutlierDetectionLoadBalancer instance
*/
@Override
public LoadBalancer newLoadBalancer(Helper helper);
/**
* Checks if the provider is available
* @return true if available
*/
@Override
public boolean isAvailable();
/**
* Gets the provider priority
* @return provider priority for selection
*/
@Override
public int getPriority();
/**
* Gets the load balancing policy name
* @return "outlier_detection_experimental"
*/
@Override
public String getPolicyName();
/**
* Parses load balancing policy configuration
* @param rawConfig raw configuration map
* @return ConfigOrError with parsed configuration or error
*/
@Override
public ConfigOrError parseLoadBalancingPolicyConfig(Map<String, ?> rawConfig);
}/**
* Endpoint wrapper for optimized address group lookup
*/
public static class Endpoint {
public Endpoint(EquivalentAddressGroup eag);
@Override
public int hashCode();
@Override
public boolean equals(Object obj);
@Override
public String toString();
}Install with Tessl CLI
npx tessl i tessl/maven-io-grpc--grpc-util