55
55
public final class RoundRobinLoadBalancerFactory <ResolvedAddress , C extends LoadBalancedConnection >
56
56
implements LoadBalancerFactory <ResolvedAddress , C > {
57
57
58
+ static final String ROUND_ROBIN_USER_DEFAULT_LOAD_BALANCER =
59
+ "io.servicetalk.loadbalancer.roundRobinUsesDefaultLoadBalancer" ;
60
+
58
61
private final String id ;
59
62
private final int linearSearchSpace ;
60
63
@ Nullable
@@ -74,17 +77,21 @@ public <T extends C> LoadBalancer<T> newLoadBalancer(
74
77
final String targetResource ,
75
78
final Publisher <? extends Collection <? extends ServiceDiscovererEvent <ResolvedAddress >>> eventPublisher ,
76
79
final ConnectionFactory <ResolvedAddress , T > connectionFactory ) {
77
- return new RoundRobinLoadBalancer <>(id , targetResource , eventPublisher , connectionFactory ,
78
- linearSearchSpace , healthCheckConfig );
80
+ // We have to indirect here instead of at the `Builder.build()` call because as it turns out
81
+ // `Builder.build()` has a return type of RoundRobinLoadBalancerFactory and is public API.
82
+ return useDefaultLoadBalancer () ?
83
+ buildDefaultLoadBalancerFactory (targetResource , eventPublisher , connectionFactory ) :
84
+ new RoundRobinLoadBalancer <>(
85
+ id , targetResource , eventPublisher , connectionFactory , linearSearchSpace , healthCheckConfig );
79
86
}
80
87
81
88
@ Override
82
89
public LoadBalancer <C > newLoadBalancer (
83
90
final Publisher <? extends Collection <? extends ServiceDiscovererEvent <ResolvedAddress >>> eventPublisher ,
84
91
final ConnectionFactory <ResolvedAddress , C > connectionFactory ,
85
92
final String targetResource ) {
86
- return new RoundRobinLoadBalancer <>( id , targetResource , eventPublisher , connectionFactory ,
87
- linearSearchSpace , healthCheckConfig );
93
+ // For now, we forward to the deprecated method since it is more generic.
94
+ return newLoadBalancer ( targetResource , eventPublisher , connectionFactory );
88
95
}
89
96
90
97
@ Override
@@ -102,6 +109,59 @@ public String toString() {
102
109
'}' ;
103
110
}
104
111
112
+ private <T extends C > LoadBalancer <T > buildDefaultLoadBalancerFactory (
113
+ final String targetResource ,
114
+ final Publisher <? extends Collection <? extends ServiceDiscovererEvent <ResolvedAddress >>> eventPublisher ,
115
+ final ConnectionFactory <ResolvedAddress , T > connectionFactory ) {
116
+ final int healthCheckFailedConnectionsThreshold ;
117
+ final Duration healthCheckInterval ;
118
+ final Duration healthCheckJitter ;
119
+ final Duration healthCheckResubscribeInterval ;
120
+ final Duration healthCheckResubscribeJitter ;
121
+ final Executor backgroundExecutor ;
122
+ if (healthCheckConfig == null ) {
123
+ healthCheckFailedConnectionsThreshold = -1 ; // disabled, the rest are fillers.
124
+ healthCheckInterval = DEFAULT_HEALTH_CHECK_INTERVAL ;
125
+ healthCheckJitter = DEFAULT_HEALTH_CHECK_JITTER ;
126
+ healthCheckResubscribeInterval = DEFAULT_HEALTH_CHECK_RESUBSCRIBE_INTERVAL ;
127
+ healthCheckResubscribeJitter = DEFAULT_HEALTH_CHECK_JITTER ;
128
+ backgroundExecutor = null ;
129
+ } else {
130
+ healthCheckFailedConnectionsThreshold = healthCheckConfig .failedThreshold ;
131
+ healthCheckInterval = healthCheckConfig .healthCheckInterval ;
132
+ healthCheckJitter = healthCheckConfig .jitter ;
133
+ healthCheckResubscribeInterval = healthCheckConfig .resubscribeInterval ;
134
+ healthCheckResubscribeJitter = healthCheckConfig .healthCheckResubscribeJitter ;
135
+ backgroundExecutor = healthCheckConfig .executor ;
136
+ }
137
+
138
+ OutlierDetectorConfig outlierDetectorConfig = new OutlierDetectorConfig .Builder ()
139
+ .ewmaHalfLife (Duration .ZERO )
140
+ // disable the xDS outlier detectors
141
+ .enforcingFailurePercentage (0 )
142
+ .enforcingSuccessRate (0 )
143
+ .enforcingConsecutive5xx (0 )
144
+ // set the ServiceTalk L4 connection outlier detector settings
145
+ .failedConnectionsThreshold (healthCheckFailedConnectionsThreshold )
146
+ .failureDetectorInterval (healthCheckInterval , healthCheckJitter )
147
+ .serviceDiscoveryResubscribeInterval (healthCheckResubscribeInterval , healthCheckResubscribeJitter )
148
+ .build ();
149
+ LoadBalancingPolicy <ResolvedAddress , T > loadBalancingPolicy =
150
+ LoadBalancingPolicies .roundRobin ()
151
+ .failOpen (false )
152
+ .ignoreWeights (true )
153
+ .build ();
154
+ LoadBalancerBuilder <ResolvedAddress , T > builder = LoadBalancers .builder (id );
155
+ if (backgroundExecutor != null ) {
156
+ builder = builder .backgroundExecutor (backgroundExecutor );
157
+ }
158
+ return builder .outlierDetectorConfig (outlierDetectorConfig )
159
+ .loadBalancingPolicy (loadBalancingPolicy )
160
+ .connectionSelectorPolicy (ConnectionSelectorPolicies .linearSearch (linearSearchSpace ))
161
+ .build ()
162
+ .newLoadBalancer (eventPublisher , connectionFactory , targetResource );
163
+ }
164
+
105
165
/**
106
166
* Builder for {@link RoundRobinLoadBalancerFactory}.
107
167
*
@@ -227,4 +287,10 @@ static Executor getInstance() {
227
287
return INSTANCE ;
228
288
}
229
289
}
290
+
291
+ private static boolean useDefaultLoadBalancer () {
292
+ // Enabled by default.
293
+ String propValue = System .getProperty (ROUND_ROBIN_USER_DEFAULT_LOAD_BALANCER );
294
+ return propValue == null || Boolean .parseBoolean (propValue );
295
+ }
230
296
}
0 commit comments