18
18
19
19
import static com .google .common .base .Preconditions .checkNotNull ;
20
20
import static io .grpc .ConnectivityState .TRANSIENT_FAILURE ;
21
+ import static io .grpc .xds .XdsLbPolicies .CDS_POLICY_NAME ;
21
22
import static io .grpc .xds .XdsLbPolicies .CLUSTER_RESOLVER_POLICY_NAME ;
23
+ import static io .grpc .xds .XdsLbPolicies .PRIORITY_POLICY_NAME ;
22
24
23
- import com .google .common .annotations .VisibleForTesting ;
24
- import com .google .common .collect .ImmutableList ;
25
25
import com .google .errorprone .annotations .CheckReturnValue ;
26
26
import io .grpc .InternalLogId ;
27
27
import io .grpc .LoadBalancer ;
33
33
import io .grpc .xds .CdsLoadBalancerProvider .CdsConfig ;
34
34
import io .grpc .xds .ClusterResolverLoadBalancerProvider .ClusterResolverConfig ;
35
35
import io .grpc .xds .ClusterResolverLoadBalancerProvider .ClusterResolverConfig .DiscoveryMechanism ;
36
+ import io .grpc .xds .PriorityLoadBalancerProvider .PriorityLbConfig .PriorityChildConfig ;
36
37
import io .grpc .xds .XdsClusterResource .CdsUpdate ;
37
38
import io .grpc .xds .XdsClusterResource .CdsUpdate .ClusterType ;
38
39
import io .grpc .xds .XdsConfig .Subscription ;
41
42
import io .grpc .xds .XdsConfig .XdsClusterConfig .EndpointConfig ;
42
43
import io .grpc .xds .client .XdsLogger ;
43
44
import io .grpc .xds .client .XdsLogger .XdsLogLevel ;
44
- import java .util .ArrayList ;
45
45
import java .util .Arrays ;
46
46
import java .util .Collections ;
47
+ import java .util .HashMap ;
47
48
import java .util .List ;
49
+ import java .util .Map ;
48
50
49
51
/**
50
52
* Load balancer for cds_experimental LB policy. One instance per top-level cluster.
@@ -55,19 +57,15 @@ final class CdsLoadBalancer2 extends LoadBalancer {
55
57
private final XdsLogger logger ;
56
58
private final Helper helper ;
57
59
private final LoadBalancerRegistry lbRegistry ;
60
+ private GracefulSwitchLoadBalancer delegate ;
58
61
// Following fields are effectively final.
59
62
private String clusterName ;
60
63
private Subscription clusterSubscription ;
61
- private LoadBalancer childLb ;
62
64
63
- CdsLoadBalancer2 (Helper helper ) {
64
- this (helper , LoadBalancerRegistry .getDefaultRegistry ());
65
- }
66
-
67
- @ VisibleForTesting
68
65
CdsLoadBalancer2 (Helper helper , LoadBalancerRegistry lbRegistry ) {
69
66
this .helper = checkNotNull (helper , "helper" );
70
67
this .lbRegistry = checkNotNull (lbRegistry , "lbRegistry" );
68
+ this .delegate = new GracefulSwitchLoadBalancer (helper );
71
69
logger = XdsLogger .withLogId (InternalLogId .allocate ("cds-lb" , helper .getAuthority ()));
72
70
logger .log (XdsLogLevel .INFO , "Created" );
73
71
}
@@ -91,7 +89,7 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
91
89
if (clusterSubscription == null ) {
92
90
// Should be impossible, because XdsDependencyManager wouldn't have generated this
93
91
return fail (Status .INTERNAL .withDescription (
94
- errorPrefix () + "Unable to find non-dynamic root cluster" ));
92
+ errorPrefix () + "Unable to find non-dynamic cluster" ));
95
93
}
96
94
// The dynamic cluster must not have loaded yet
97
95
return Status .OK ;
@@ -100,42 +98,25 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
100
98
return fail (clusterConfigOr .getStatus ());
101
99
}
102
100
XdsClusterConfig clusterConfig = clusterConfigOr .getValue ();
103
- List <String > leafNames ;
104
- if (clusterConfig .getChildren () instanceof AggregateConfig ) {
105
- leafNames = ((AggregateConfig ) clusterConfig .getChildren ()).getLeafNames ();
106
- } else if (clusterConfig .getChildren () instanceof EndpointConfig ) {
107
- leafNames = ImmutableList .of (clusterName );
108
- } else {
109
- return fail (Status .INTERNAL .withDescription (
110
- errorPrefix () + "Unexpected cluster children type: "
111
- + clusterConfig .getChildren ().getClass ()));
112
- }
113
- if (leafNames .isEmpty ()) {
114
- // Should be impossible, because XdsClusterResource validated this
115
- return fail (Status .UNAVAILABLE .withDescription (
116
- errorPrefix () + "Zero leaf clusters for root cluster " + clusterName ));
117
- }
118
101
119
- Status noneFoundError = Status .INTERNAL
120
- .withDescription (errorPrefix () + "No leaves and no error; this is a bug" );
121
- List <DiscoveryMechanism > instances = new ArrayList <>();
122
- for (String leafName : leafNames ) {
123
- StatusOr <XdsClusterConfig > leafConfigOr = xdsConfig .getClusters ().get (leafName );
124
- if (!leafConfigOr .hasValue ()) {
125
- noneFoundError = leafConfigOr .getStatus ();
126
- continue ;
127
- }
128
- if (!(leafConfigOr .getValue ().getChildren () instanceof EndpointConfig )) {
129
- noneFoundError = Status .INTERNAL .withDescription (
130
- errorPrefix () + "Unexpected child " + leafName + " cluster children type: "
131
- + leafConfigOr .getValue ().getChildren ().getClass ());
132
- continue ;
102
+ NameResolver .ConfigOrError configOrError ;
103
+ Object gracefulConfig ;
104
+ if (clusterConfig .getChildren () instanceof EndpointConfig ) {
105
+ // The LB policy config is provided in service_config.proto/JSON format.
106
+ configOrError =
107
+ GracefulSwitchLoadBalancer .parseLoadBalancingPolicyConfig (
108
+ Arrays .asList (clusterConfig .getClusterResource ().lbPolicyConfig ()),
109
+ lbRegistry );
110
+ if (configOrError .getError () != null ) {
111
+ // Should be impossible, because XdsClusterResource validated this
112
+ return fail (Status .INTERNAL .withDescription (
113
+ errorPrefix () + "Unable to parse the LB config: " + configOrError .getError ()));
133
114
}
134
- CdsUpdate result = leafConfigOr . getValue () .getClusterResource ();
115
+ CdsUpdate result = clusterConfig .getClusterResource ();
135
116
DiscoveryMechanism instance ;
136
117
if (result .clusterType () == ClusterType .EDS ) {
137
118
instance = DiscoveryMechanism .forEds (
138
- leafName ,
119
+ clusterName ,
139
120
result .edsServiceName (),
140
121
result .lrsServerInfo (),
141
122
result .maxConcurrentRequests (),
@@ -144,45 +125,49 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
144
125
result .outlierDetection ());
145
126
} else {
146
127
instance = DiscoveryMechanism .forLogicalDns (
147
- leafName ,
128
+ clusterName ,
148
129
result .dnsHostName (),
149
130
result .lrsServerInfo (),
150
131
result .maxConcurrentRequests (),
151
132
result .upstreamTlsContext (),
152
133
result .filterMetadata ());
153
134
}
154
- instances .add (instance );
155
- }
156
- if (instances .isEmpty ()) {
157
- return fail (noneFoundError );
158
- }
159
-
160
- // The LB policy config is provided in service_config.proto/JSON format.
161
- NameResolver .ConfigOrError configOrError =
162
- GracefulSwitchLoadBalancer .parseLoadBalancingPolicyConfig (
163
- Arrays .asList (clusterConfig .getClusterResource ().lbPolicyConfig ()), lbRegistry );
164
- if (configOrError .getError () != null ) {
165
- // Should be impossible, because XdsClusterResource validated this
135
+ gracefulConfig = GracefulSwitchLoadBalancer .createLoadBalancingPolicyConfig (
136
+ lbRegistry .getProvider (CLUSTER_RESOLVER_POLICY_NAME ),
137
+ new ClusterResolverConfig (
138
+ instance ,
139
+ configOrError .getConfig (),
140
+ clusterConfig .getClusterResource ().isHttp11ProxyAvailable ()));
141
+ } else if (clusterConfig .getChildren () instanceof AggregateConfig ) {
142
+ Map <String , PriorityChildConfig > priorityChildConfigs = new HashMap <>();
143
+ List <String > leafClusters = ((AggregateConfig ) clusterConfig .getChildren ()).getLeafNames ();
144
+ for (String childCluster : leafClusters ) {
145
+ priorityChildConfigs .put (childCluster ,
146
+ new PriorityChildConfig (
147
+ GracefulSwitchLoadBalancer .createLoadBalancingPolicyConfig (
148
+ lbRegistry .getProvider (CDS_POLICY_NAME ),
149
+ new CdsConfig (childCluster )),
150
+ false ));
151
+ }
152
+ gracefulConfig = GracefulSwitchLoadBalancer .createLoadBalancingPolicyConfig (
153
+ lbRegistry .getProvider (PRIORITY_POLICY_NAME ),
154
+ new PriorityLoadBalancerProvider .PriorityLbConfig (
155
+ Collections .unmodifiableMap (priorityChildConfigs ), leafClusters ));
156
+ } else {
166
157
return fail (Status .INTERNAL .withDescription (
167
- errorPrefix () + "Unable to parse the LB config: " + configOrError .getError ()));
158
+ errorPrefix () + "Unexpected cluster children type: "
159
+ + clusterConfig .getChildren ().getClass ()));
168
160
}
169
161
170
- ClusterResolverConfig config = new ClusterResolverConfig (
171
- Collections .unmodifiableList (instances ),
172
- configOrError .getConfig (),
173
- clusterConfig .getClusterResource ().isHttp11ProxyAvailable ());
174
- if (childLb == null ) {
175
- childLb = lbRegistry .getProvider (CLUSTER_RESOLVER_POLICY_NAME ).newLoadBalancer (helper );
176
- }
177
- return childLb .acceptResolvedAddresses (
178
- resolvedAddresses .toBuilder ().setLoadBalancingPolicyConfig (config ).build ());
162
+ return delegate .acceptResolvedAddresses (
163
+ resolvedAddresses .toBuilder ().setLoadBalancingPolicyConfig (gracefulConfig ).build ());
179
164
}
180
165
181
166
@ Override
182
167
public void handleNameResolutionError (Status error ) {
183
168
logger .log (XdsLogLevel .WARNING , "Received name resolution error: {0}" , error );
184
- if (childLb != null ) {
185
- childLb .handleNameResolutionError (error );
169
+ if (delegate != null ) {
170
+ delegate .handleNameResolutionError (error );
186
171
} else {
187
172
helper .updateBalancingState (
188
173
TRANSIENT_FAILURE , new FixedResultPicker (PickResult .withError (error )));
@@ -192,10 +177,8 @@ public void handleNameResolutionError(Status error) {
192
177
@ Override
193
178
public void shutdown () {
194
179
logger .log (XdsLogLevel .INFO , "Shutdown" );
195
- if (childLb != null ) {
196
- childLb .shutdown ();
197
- childLb = null ;
198
- }
180
+ delegate .shutdown ();
181
+ delegate = new GracefulSwitchLoadBalancer (helper );
199
182
if (clusterSubscription != null ) {
200
183
clusterSubscription .close ();
201
184
clusterSubscription = null ;
@@ -204,10 +187,7 @@ public void shutdown() {
204
187
205
188
@ CheckReturnValue // don't forget to return up the stack after the fail call
206
189
private Status fail (Status error ) {
207
- if (childLb != null ) {
208
- childLb .shutdown ();
209
- childLb = null ;
210
- }
190
+ delegate .shutdown ();
211
191
helper .updateBalancingState (
212
192
TRANSIENT_FAILURE , new FixedResultPicker (PickResult .withError (error )));
213
193
return Status .OK ; // XdsNameResolver isn't a polling NR, so this value doesn't matter
0 commit comments