Skip to content

Commit

Permalink
Cleanup the builder interface
Browse files Browse the repository at this point in the history
  • Loading branch information
bryce-anderson committed Mar 7, 2024
1 parent 06d1071 commit c393042
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,7 @@ final class DefaultLoadBalancerBuilder<ResolvedAddress, C extends LoadBalancedCo
private Executor backgroundExecutor;
@Nullable
private LoadBalancerObserver<ResolvedAddress> loadBalancerObserver;
@Nullable
private OutlierDetectorFactory<ResolvedAddress, C> outlierDetectorFactory;
private Duration healthCheckInterval = DEFAULT_HEALTH_CHECK_INTERVAL;
private Duration healthCheckJitter = DEFAULT_HEALTH_CHECK_JITTER;
private int healthCheckFailedConnectionsThreshold = DEFAULT_HEALTH_CHECK_FAILED_CONNECTIONS_THRESHOLD;
private OutlierDetectorConfig outlierDetectorConfig = OutlierDetectorConfig.DEFAULT_CONFIG;
private Duration healthCheckResubscribeInterval = DEFAULT_HEALTH_CHECK_RESUBSCRIBE_INTERVAL;
private Duration healthCheckResubscribeJitter = DEFAULT_HEALTH_CHECK_JITTER;

Expand Down Expand Up @@ -85,9 +81,10 @@ public LoadBalancerBuilder<ResolvedAddress, C> loadBalancerObserver(
}

@Override
public LoadBalancerBuilder<ResolvedAddress, C> outlierDetectorFactory(
OutlierDetectorFactory<ResolvedAddress, C> outlierDetectorFactory) {
this.outlierDetectorFactory = outlierDetectorFactory;
public LoadBalancerBuilder<ResolvedAddress, C> outlierDetectorConfig(
@Nullable OutlierDetectorConfig outlierDetectorConfig) {
this.outlierDetectorConfig = outlierDetectorConfig == null ?
OutlierDetectorConfig.DEFAULT_CONFIG : outlierDetectorConfig;
return this;
}

Expand All @@ -97,14 +94,6 @@ public LoadBalancerBuilder<ResolvedAddress, C> backgroundExecutor(Executor backg
return this;
}

@Override
public LoadBalancerBuilder<ResolvedAddress, C> healthCheckInterval(Duration interval, Duration jitter) {
validateHealthCheckIntervals(interval, jitter);
this.healthCheckInterval = interval;
this.healthCheckJitter = jitter;
return this;
}

@Override
public LoadBalancerBuilder<ResolvedAddress, C> healthCheckResubscribeInterval(
Duration interval, Duration jitter) {
Expand All @@ -114,37 +103,23 @@ public LoadBalancerBuilder<ResolvedAddress, C> healthCheckResubscribeInterval(
return this;
}

@Override
public LoadBalancerBuilder<ResolvedAddress, C> healthCheckFailedConnectionsThreshold(
int threshold) {
if (threshold == 0) {
throw new IllegalArgumentException("Invalid health-check failed connections (expected != 0)");
}
this.healthCheckFailedConnectionsThreshold = threshold;
return this;
}

@Override
public LoadBalancerFactory<ResolvedAddress, C> build() {
final HealthCheckConfig healthCheckConfig;
if (this.healthCheckFailedConnectionsThreshold < 0) {
final Executor executor = getExecutor();
if (outlierDetectorConfig.failedConnectionsThreshold() < 0) {
healthCheckConfig = null;
} else {
healthCheckConfig = new HealthCheckConfig(getExecutor(),
healthCheckInterval, healthCheckJitter, healthCheckFailedConnectionsThreshold,
healthCheckConfig = new HealthCheckConfig(executor,
outlierDetectorConfig.failedConnectionsProbeInterval(),
outlierDetectorConfig.failedConnectionsProbeJitter(),
outlierDetectorConfig.failedConnectionsThreshold(),
healthCheckResubscribeInterval, healthCheckResubscribeJitter);
}
final LoadBalancerObserver<ResolvedAddress> loadBalancerObserver = this.loadBalancerObserver != null ?
this.loadBalancerObserver : NoopLoadBalancerObserver.instance();
Function<String, OutlierDetector<ResolvedAddress, C>> healthCheckerSupplier;
if (outlierDetectorFactory == null) {
healthCheckerSupplier = null;
} else {
final Executor executor = getExecutor();
healthCheckerSupplier = (String lbDescrption) ->
outlierDetectorFactory.newHealthChecker(executor, lbDescrption);
}

Function<String, OutlierDetector<ResolvedAddress, C>> healthCheckerSupplier =
(String lbDescription) -> new XdsOutlierDetector<>(executor, outlierDetectorConfig, lbDescription);
return new DefaultLoadBalancerFactory<>(id, loadBalancingPolicy, linearSearchSpace, healthCheckConfig,
loadBalancerObserver, healthCheckerSupplier);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import io.servicetalk.client.api.ScoreSupplier;

import java.time.Duration;
import java.util.concurrent.locks.StampedLock;

import static io.servicetalk.utils.internal.NumberUtils.ensurePositive;
Expand All @@ -39,6 +40,8 @@
*/
abstract class DefaultRequestTracker implements RequestTracker, ScoreSupplier {
private static final long MAX_MS_TO_NS = NANOSECONDS.convert(MAX_VALUE, MILLISECONDS);

static final Duration DEFAULT_EWMA_HALF_LIFE = Duration.ofSeconds(10);
static final long DEFAULT_CANCEL_PENALTY = 5L;
static final long DEFAULT_ERROR_PENALTY = 10L;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,28 +84,20 @@ LoadBalancerBuilder<ResolvedAddress, C> loadBalancerObserver(
@Nullable LoadBalancerObserver<ResolvedAddress> loadBalancerObserver);

/**
* Set the {@link OutlierDetectorFactory} to use with this load balancer.
* @param outlierDetectorFactory the {@link OutlierDetectorFactory} to use, or {@code null} to not use a
* {@link OutlierDetector}.
* Set the {@link OutlierDetectorConfig} to use with this load balancer.
* @param outlierDetectorConfig the {@link OutlierDetectorConfig} to use, or {@code null} to use the default
* outlier detection.
* @return {code this}
*/
LoadBalancerBuilder<ResolvedAddress, C> outlierDetectorFactory(
OutlierDetectorFactory<ResolvedAddress, C> outlierDetectorFactory);
LoadBalancerBuilder<ResolvedAddress, C> outlierDetectorConfig(
@Nullable OutlierDetectorConfig outlierDetectorConfig);

/**
* This {@link LoadBalancer} may monitor hosts to which connection establishment has failed
* using health checks that run in the background. The health check tries to establish a new connection
* and if it succeeds, the host is returned to the load balancing pool. As long as the connection
* establishment fails, the host is not considered for opening new connections for processed requests.
* If an {@link Executor} is not provided using this method, a default shared instance is used
* for all {@link LoadBalancer LoadBalancers} created by this factory.
* <p>
* {@link #healthCheckFailedConnectionsThreshold(int)} can be used to disable this mechanism and always
* consider all hosts for establishing new connections.
* Set the background {@link Executor} to use for determining time and scheduling background tasks such
* as those associated with outlier detection.
*
* @param backgroundExecutor {@link Executor} on which to schedule health checking.
* @param backgroundExecutor {@link Executor} to use as a time source and for scheduling background tasks.
* @return {@code this}.
* @see #healthCheckFailedConnectionsThreshold(int)
*/
LoadBalancerBuilder<ResolvedAddress, C> backgroundExecutor(Executor backgroundExecutor);

Expand All @@ -125,22 +117,6 @@ LoadBalancerBuilder<ResolvedAddress, C> outlierDetectorFactory(
*/
LoadBalancerBuilder<ResolvedAddress, C> linearSearchSpace(int linearSearchSpace);

// TODO: these healthCheck* methods should be moved into their own OutlierDetection configuration instance
// and much like the LoadBalancingPolicy, we should be able to add `OutlierDetectionPolicy`s
/**
* Configure an interval for health checking a host that failed to open connections. If no interval is provided
* using this method, a default value will be used.
* <p>
* {@link #healthCheckFailedConnectionsThreshold(int)} can be used to disable the health checking mechanism
* and always consider all hosts for establishing new connections.
*
* @param interval interval at which a background health check will be scheduled.
* @param jitter the amount of jitter to apply to each retry {@code interval}.
* @return {@code this}.
* @see #healthCheckFailedConnectionsThreshold(int)
*/
LoadBalancerBuilder<ResolvedAddress, C> healthCheckInterval(Duration interval, Duration jitter);

/**
* Configure an interval for re-subscribing to the original events stream in case all existing hosts become
* unhealthy.
Expand All @@ -149,32 +125,15 @@ LoadBalancerBuilder<ResolvedAddress, C> outlierDetectorFactory(
* known hosts become unhealthy, which could happen due to intermediate caching layers, re-subscribe to the
* events stream can help to exit from a dead state.
* <p>
* {@link #healthCheckFailedConnectionsThreshold(int)} can be used to disable the health checking mechanism
* and always consider all hosts for establishing new connections.
* Note: setting the interval to {@code Duration.ofNanos(Long.MAX_VALUE)} will effectively disable health check
* resubscribes.
*
* @param interval interval at which re-subscribes will be scheduled.
* @param jitter the amount of jitter to apply to each re-subscribe {@code interval}.
* @return {@code this}.
* @see #healthCheckFailedConnectionsThreshold(int)
*/
LoadBalancerBuilder<ResolvedAddress, C> healthCheckResubscribeInterval(Duration interval, Duration jitter);

/**
* Configure a threshold for consecutive connection failures to a host. When the {@link LoadBalancer}
* consecutively fails to open connections in the amount greater or equal to the specified value,
* the host will be marked as unhealthy and connection establishment will take place in the background
* repeatedly until a connection is established. During that time, the host will not take part in
* load balancing selection.
* <p>
* Use a negative value of the argument to disable health checking.
*
* @param threshold number of consecutive connection failures to consider a host unhealthy and eligible for
* background health checking. Use negative value to disable the health checking mechanism.
* @return {@code this}.
* @see #backgroundExecutor(Executor)
*/
LoadBalancerBuilder<ResolvedAddress, C> healthCheckFailedConnectionsThreshold(int threshold);

/**
* Builds the {@link LoadBalancerFactory} configured by this builder.
*
Expand Down
Loading

0 comments on commit c393042

Please sign in to comment.