diff --git a/servicetalk-loadbalancer-experimental-provider/src/main/java/io/servicetalk/loadbalancer/experimental/DefaultLoadBalancerObserver.java b/servicetalk-loadbalancer-experimental-provider/src/main/java/io/servicetalk/loadbalancer/experimental/DefaultLoadBalancerObserver.java index e68f110140..2c9c565f7e 100644 --- a/servicetalk-loadbalancer-experimental-provider/src/main/java/io/servicetalk/loadbalancer/experimental/DefaultLoadBalancerObserver.java +++ b/servicetalk-loadbalancer-experimental-provider/src/main/java/io/servicetalk/loadbalancer/experimental/DefaultLoadBalancerObserver.java @@ -59,6 +59,20 @@ public void onNoActiveHostsAvailable(int hostSetSize, NoActiveHostException exce LOGGER.debug("{}- No active hosts available. Host set size: {}.", lbDescription, hostSetSize, exception); } + @Override + public void onHostSetChanged(Collection newHosts) { + if (LOGGER.isDebugEnabled()) { + int healthyCount = 0; + for (Host host : newHosts) { + if (host.isHealthy()) { + healthyCount++; + } + } + LOGGER.debug("{}- onHostSetChanged(host set size: {}, healthy: {}). New hosts: {}", lbDescription, + newHosts.size(), healthyCount, newHosts); + } + } + private final class HostObserverImpl implements HostObserver { private final Object resolvedAddress; diff --git a/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/DefaultLoadBalancer.java b/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/DefaultLoadBalancer.java index df8d48aa69..b95c0b57b9 100644 --- a/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/DefaultLoadBalancer.java +++ b/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/DefaultLoadBalancer.java @@ -508,7 +508,9 @@ private void sequentialUpdateUsedHosts(List host : nextHosts) { host.loadBalancingWeight(host.serviceDiscoveryWeight()); } - this.hostSelector = hostSelector.rebuildWithHosts(priorityStrategy.prioritize(usedHosts)); + nextHosts = priorityStrategy.prioritize(nextHosts); + this.hostSelector = hostSelector.rebuildWithHosts(nextHosts); + loadBalancerObserver.onHostSetChanged(Collections.unmodifiableList(nextHosts)); } @Override @@ -649,7 +651,7 @@ List> hosts() { } static final class PrioritizedHostImpl - implements Host, PrioritizedHost { + implements Host, PrioritizedHost, LoadBalancerObserver.Host { private final Host delegate; private int priority; private double serviceDiscoveryWeight; diff --git a/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/LoadBalancerObserver.java b/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/LoadBalancerObserver.java index e4b5c5c1fc..8e1b363a4b 100644 --- a/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/LoadBalancerObserver.java +++ b/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/LoadBalancerObserver.java @@ -55,7 +55,17 @@ void onServiceDiscoveryEvent(Collection> eve void onNoActiveHostsAvailable(int hostSetSize, NoActiveHostException exception); /** - * An observer for {@link Host} events. + * Callback for when the set of hosts used by the load balancer has changed. This set may not + * exactly reflect the state of the service discovery system due to filtering of zero-weight + * hosts and forms of sub-setting and thus may only represent the hosts that the selection + * algorithm may use. + * @param newHosts the new set of hosts used by the selection algorithm. + */ + default void onHostSetChanged(Collection newHosts) { + } + + /** + * An observer for {@link io.servicetalk.loadbalancer.Host} events. */ interface HostObserver { @@ -84,14 +94,38 @@ interface HostObserver { void onExpiredHostRemoved(int connectionCount); /** - * Callback for when a {@link Host} transitions from healthy to unhealthy. + * Callback for when a {@link io.servicetalk.loadbalancer.Host} transitions from healthy to unhealthy. * @param cause the most recent cause of the transition. */ void onHostMarkedUnhealthy(@Nullable Throwable cause); /** - * Callback for when a {@link Host} transitions from unhealthy to healthy. + * Callback for when a {@link io.servicetalk.loadbalancer.Host} transitions from unhealthy to healthy. */ void onHostRevived(); } + + /** + * A description of a host. + */ + interface Host { + /** + * The address of the host. + * @return the address of the host. + */ + Object address(); + + /** + * Determine the health status of this host. + * @return whether the host considers itself healthy enough to serve traffic. This is best effort and does not + * guarantee that the request will succeed. + */ + boolean isHealthy(); + + /** + * The weight of the host, relative to the weights of associated hosts as used for load balancing. + * @return the relative weight of the host. + */ + double loadBalancingWeight(); + } } diff --git a/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/NoopLoadBalancerObserver.java b/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/NoopLoadBalancerObserver.java index 29693dd45b..234b7bbbcb 100644 --- a/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/NoopLoadBalancerObserver.java +++ b/servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/NoopLoadBalancerObserver.java @@ -51,6 +51,11 @@ public void onServiceDiscoveryEvent(Collection newHosts) { + // noop + } + private static final class NoopHostObserver implements LoadBalancerObserver.HostObserver { private static final HostObserver INSTANCE = new NoopHostObserver();