mirror of https://github.com/grpc/grpc-java.git
xds: run watcher callbacks in its own channel synchronization context (#7525)
In the context of sharing the XdsClient instance between Channels, watcher callbacks need to be executed in each Channel's own SynchronizationContext.
This commit is contained in:
parent
0b6e6e5fd5
commit
19485014fd
|
|
@ -29,6 +29,7 @@ import io.grpc.LoadBalancer;
|
||||||
import io.grpc.LoadBalancerProvider;
|
import io.grpc.LoadBalancerProvider;
|
||||||
import io.grpc.LoadBalancerRegistry;
|
import io.grpc.LoadBalancerRegistry;
|
||||||
import io.grpc.Status;
|
import io.grpc.Status;
|
||||||
|
import io.grpc.SynchronizationContext;
|
||||||
import io.grpc.internal.ObjectPool;
|
import io.grpc.internal.ObjectPool;
|
||||||
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
|
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
|
||||||
import io.grpc.util.ForwardingLoadBalancerHelper;
|
import io.grpc.util.ForwardingLoadBalancerHelper;
|
||||||
|
|
@ -52,6 +53,7 @@ import javax.annotation.Nullable;
|
||||||
final class CdsLoadBalancer extends LoadBalancer {
|
final class CdsLoadBalancer extends LoadBalancer {
|
||||||
private final XdsLogger logger;
|
private final XdsLogger logger;
|
||||||
private final Helper helper;
|
private final Helper helper;
|
||||||
|
private final SynchronizationContext syncContext;
|
||||||
private final LoadBalancerRegistry lbRegistry;
|
private final LoadBalancerRegistry lbRegistry;
|
||||||
private final TlsContextManager tlsContextManager;
|
private final TlsContextManager tlsContextManager;
|
||||||
// TODO(sanjaypujare): remove once xds security is released
|
// TODO(sanjaypujare): remove once xds security is released
|
||||||
|
|
@ -71,6 +73,7 @@ final class CdsLoadBalancer extends LoadBalancer {
|
||||||
CdsLoadBalancer(Helper helper, LoadBalancerRegistry lbRegistry,
|
CdsLoadBalancer(Helper helper, LoadBalancerRegistry lbRegistry,
|
||||||
TlsContextManager tlsContextManager) {
|
TlsContextManager tlsContextManager) {
|
||||||
this.helper = checkNotNull(helper, "helper");
|
this.helper = checkNotNull(helper, "helper");
|
||||||
|
this.syncContext = checkNotNull(helper.getSynchronizationContext(), "syncContext");
|
||||||
this.lbRegistry = lbRegistry;
|
this.lbRegistry = lbRegistry;
|
||||||
this.tlsContextManager = tlsContextManager;
|
this.tlsContextManager = tlsContextManager;
|
||||||
logger = XdsLogger.withLogId(InternalLogId.allocate("cds-lb", helper.getAuthority()));
|
logger = XdsLogger.withLogId(InternalLogId.allocate("cds-lb", helper.getAuthority()));
|
||||||
|
|
@ -179,6 +182,7 @@ final class CdsLoadBalancer extends LoadBalancer {
|
||||||
|
|
||||||
private final class CdsLbState implements CdsResourceWatcher {
|
private final class CdsLbState implements CdsResourceWatcher {
|
||||||
private final ChannelSecurityLbHelper lbHelper = new ChannelSecurityLbHelper();
|
private final ChannelSecurityLbHelper lbHelper = new ChannelSecurityLbHelper();
|
||||||
|
private boolean shutdown;
|
||||||
@Nullable
|
@Nullable
|
||||||
LoadBalancer edsBalancer;
|
LoadBalancer edsBalancer;
|
||||||
|
|
||||||
|
|
@ -189,37 +193,43 @@ final class CdsLoadBalancer extends LoadBalancer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(CdsUpdate newUpdate) {
|
public void onChanged(final CdsUpdate newUpdate) {
|
||||||
if (logger.isLoggable(XdsLogLevel.INFO)) {
|
syncContext.execute(new Runnable() {
|
||||||
logger.log(
|
@Override
|
||||||
XdsLogLevel.INFO,
|
public void run() {
|
||||||
"Received cluster update from xDS client {0}: "
|
if (shutdown) {
|
||||||
+ "cluster_name={1}, eds_service_name={2}, lb_policy={3}, report_load={4}",
|
return;
|
||||||
xdsClient, newUpdate.getClusterName(), newUpdate.getEdsServiceName(),
|
}
|
||||||
newUpdate.getLbPolicy(), newUpdate.getLrsServerName() != null);
|
if (logger.isLoggable(XdsLogLevel.INFO)) {
|
||||||
}
|
logger.log(XdsLogLevel.INFO, "Received cluster update from xDS client {0}: "
|
||||||
// FIXME(chengyuanzhang): handle error correctly to avoid being unnecessarily fragile.
|
+ "cluster_name={1}, eds_service_name={2}, lb_policy={3}, report_load={4}",
|
||||||
checkArgument(
|
xdsClient, newUpdate.getClusterName(), newUpdate.getEdsServiceName(),
|
||||||
newUpdate.getLbPolicy().equals("round_robin"), "can only support round_robin policy");
|
newUpdate.getLbPolicy(), newUpdate.getLrsServerName() != null);
|
||||||
LoadBalancerProvider endpointPickingPolicyProvider =
|
}
|
||||||
lbRegistry.getProvider(newUpdate.getLbPolicy());
|
// FIXME(chengyuanzhang): handle error correctly to avoid being unnecessarily fragile.
|
||||||
LoadBalancerProvider localityPickingPolicyProvider =
|
checkArgument(newUpdate.getLbPolicy().equals("round_robin"),
|
||||||
lbRegistry.getProvider(WEIGHTED_TARGET_POLICY_NAME); // hardcode to weighted-target
|
"can only support round_robin policy");
|
||||||
final EdsConfig edsConfig =
|
LoadBalancerProvider endpointPickingPolicyProvider =
|
||||||
new EdsConfig(
|
lbRegistry.getProvider(newUpdate.getLbPolicy());
|
||||||
/* clusterName = */ newUpdate.getClusterName(),
|
LoadBalancerProvider localityPickingPolicyProvider =
|
||||||
/* edsServiceName = */ newUpdate.getEdsServiceName(),
|
lbRegistry.getProvider(WEIGHTED_TARGET_POLICY_NAME); // hardcode to weighted-target
|
||||||
/* lrsServerName = */ newUpdate.getLrsServerName(),
|
final EdsConfig edsConfig =
|
||||||
new PolicySelection(localityPickingPolicyProvider, null /* by EDS policy */),
|
new EdsConfig(
|
||||||
new PolicySelection(endpointPickingPolicyProvider, null));
|
/* clusterName = */ newUpdate.getClusterName(),
|
||||||
if (isXdsSecurityEnabled()) {
|
/* edsServiceName = */ newUpdate.getEdsServiceName(),
|
||||||
updateSslContextProviderSupplier(newUpdate.getUpstreamTlsContext());
|
/* lrsServerName = */ newUpdate.getLrsServerName(),
|
||||||
}
|
new PolicySelection(localityPickingPolicyProvider, null /* by EDS policy */),
|
||||||
if (edsBalancer == null) {
|
new PolicySelection(endpointPickingPolicyProvider, null));
|
||||||
edsBalancer = lbRegistry.getProvider(EDS_POLICY_NAME).newLoadBalancer(lbHelper);
|
if (isXdsSecurityEnabled()) {
|
||||||
}
|
updateSslContextProviderSupplier(newUpdate.getUpstreamTlsContext());
|
||||||
edsBalancer.handleResolvedAddresses(
|
}
|
||||||
resolvedAddresses.toBuilder().setLoadBalancingPolicyConfig(edsConfig).build());
|
if (edsBalancer == null) {
|
||||||
|
edsBalancer = lbRegistry.getProvider(EDS_POLICY_NAME).newLoadBalancer(lbHelper);
|
||||||
|
}
|
||||||
|
edsBalancer.handleResolvedAddresses(
|
||||||
|
resolvedAddresses.toBuilder().setLoadBalancingPolicyConfig(edsConfig).build());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** For new UpstreamTlsContext value, release old SslContextProvider. */
|
/** For new UpstreamTlsContext value, release old SslContextProvider. */
|
||||||
|
|
@ -244,32 +254,49 @@ final class CdsLoadBalancer extends LoadBalancer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResourceDoesNotExist(String resourceName) {
|
public void onResourceDoesNotExist(final String resourceName) {
|
||||||
logger.log(XdsLogLevel.INFO, "Resource {0} is unavailable", resourceName);
|
syncContext.execute(new Runnable() {
|
||||||
if (edsBalancer != null) {
|
@Override
|
||||||
edsBalancer.shutdown();
|
public void run() {
|
||||||
edsBalancer = null;
|
if (shutdown) {
|
||||||
}
|
return;
|
||||||
helper.updateBalancingState(
|
}
|
||||||
TRANSIENT_FAILURE,
|
logger.log(XdsLogLevel.INFO, "Resource {0} is unavailable", resourceName);
|
||||||
new ErrorPicker(
|
if (edsBalancer != null) {
|
||||||
Status.UNAVAILABLE.withDescription("Resource " + resourceName + " is unavailable")));
|
edsBalancer.shutdown();
|
||||||
|
edsBalancer = null;
|
||||||
|
}
|
||||||
|
helper.updateBalancingState(
|
||||||
|
TRANSIENT_FAILURE,
|
||||||
|
new ErrorPicker(Status.UNAVAILABLE.withDescription(
|
||||||
|
"Resource " + resourceName + " is unavailable")));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Status error) {
|
public void onError(final Status error) {
|
||||||
logger.log(
|
syncContext.execute(new Runnable() {
|
||||||
XdsLogLevel.WARNING,
|
@Override
|
||||||
"Received error from xDS client {0}: {1}: {2}",
|
public void run() {
|
||||||
xdsClient,
|
if (shutdown) {
|
||||||
error.getCode(),
|
return;
|
||||||
error.getDescription());
|
}
|
||||||
if (edsBalancer == null) {
|
logger.log(
|
||||||
helper.updateBalancingState(TRANSIENT_FAILURE, new ErrorPicker(error));
|
XdsLogLevel.WARNING,
|
||||||
}
|
"Received error from xDS client {0}: {1}: {2}",
|
||||||
|
xdsClient,
|
||||||
|
error.getCode(),
|
||||||
|
error.getDescription());
|
||||||
|
if (edsBalancer == null) {
|
||||||
|
helper.updateBalancingState(TRANSIENT_FAILURE, new ErrorPicker(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
|
shutdown = true;
|
||||||
xdsClient.cancelCdsResourceWatch(clusterName, this);
|
xdsClient.cancelCdsResourceWatch(clusterName, this);
|
||||||
logger.log(XdsLogLevel.INFO,
|
logger.log(XdsLogLevel.INFO,
|
||||||
"Cancelled watcher for cluster {0} with xDS client {1}", clusterName, xdsClient);
|
"Cancelled watcher for cluster {0} with xDS client {1}", clusterName, xdsClient);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import io.grpc.LoadBalancer;
|
||||||
import io.grpc.LoadBalancerProvider;
|
import io.grpc.LoadBalancerProvider;
|
||||||
import io.grpc.LoadBalancerRegistry;
|
import io.grpc.LoadBalancerRegistry;
|
||||||
import io.grpc.Status;
|
import io.grpc.Status;
|
||||||
|
import io.grpc.SynchronizationContext;
|
||||||
import io.grpc.internal.ObjectPool;
|
import io.grpc.internal.ObjectPool;
|
||||||
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
|
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
|
||||||
import io.grpc.util.ForwardingLoadBalancerHelper;
|
import io.grpc.util.ForwardingLoadBalancerHelper;
|
||||||
|
|
@ -60,6 +61,7 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
final class EdsLoadBalancer2 extends LoadBalancer {
|
final class EdsLoadBalancer2 extends LoadBalancer {
|
||||||
private final XdsLogger logger;
|
private final XdsLogger logger;
|
||||||
|
private final SynchronizationContext syncContext;
|
||||||
private final LoadBalancerRegistry lbRegistry;
|
private final LoadBalancerRegistry lbRegistry;
|
||||||
private final ThreadSafeRandom random;
|
private final ThreadSafeRandom random;
|
||||||
private final GracefulSwitchLoadBalancer switchingLoadBalancer;
|
private final GracefulSwitchLoadBalancer switchingLoadBalancer;
|
||||||
|
|
@ -77,7 +79,8 @@ final class EdsLoadBalancer2 extends LoadBalancer {
|
||||||
LoadBalancer.Helper helper, LoadBalancerRegistry lbRegistry, ThreadSafeRandom random) {
|
LoadBalancer.Helper helper, LoadBalancerRegistry lbRegistry, ThreadSafeRandom random) {
|
||||||
this.lbRegistry = checkNotNull(lbRegistry, "lbRegistry");
|
this.lbRegistry = checkNotNull(lbRegistry, "lbRegistry");
|
||||||
this.random = checkNotNull(random, "random");
|
this.random = checkNotNull(random, "random");
|
||||||
switchingLoadBalancer = new GracefulSwitchLoadBalancer(checkNotNull(helper, "helper"));
|
syncContext = checkNotNull(helper, "helper").getSynchronizationContext();
|
||||||
|
switchingLoadBalancer = new GracefulSwitchLoadBalancer(helper);
|
||||||
InternalLogId logId = InternalLogId.allocate("eds-lb", helper.getAuthority());
|
InternalLogId logId = InternalLogId.allocate("eds-lb", helper.getAuthority());
|
||||||
logger = XdsLogger.withLogId(logId);
|
logger = XdsLogger.withLogId(logId);
|
||||||
logger.log(XdsLogLevel.INFO, "Created");
|
logger.log(XdsLogLevel.INFO, "Created");
|
||||||
|
|
@ -156,6 +159,7 @@ final class EdsLoadBalancer2 extends LoadBalancer {
|
||||||
private ResolvedAddresses resolvedAddresses;
|
private ResolvedAddresses resolvedAddresses;
|
||||||
private PolicySelection localityPickingPolicy;
|
private PolicySelection localityPickingPolicy;
|
||||||
private PolicySelection endpointPickingPolicy;
|
private PolicySelection endpointPickingPolicy;
|
||||||
|
private boolean shutdown;
|
||||||
@Nullable
|
@Nullable
|
||||||
private LoadBalancer lb;
|
private LoadBalancer lb;
|
||||||
|
|
||||||
|
|
@ -216,6 +220,7 @@ final class EdsLoadBalancer2 extends LoadBalancer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
shutdown = true;
|
||||||
if (lrsServerName != null) {
|
if (lrsServerName != null) {
|
||||||
xdsClient.removeClientStats(cluster, edsServiceName);
|
xdsClient.removeClientStats(cluster, edsServiceName);
|
||||||
}
|
}
|
||||||
|
|
@ -234,89 +239,112 @@ final class EdsLoadBalancer2 extends LoadBalancer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(EdsUpdate update) {
|
public void onChanged(final EdsUpdate update) {
|
||||||
logger.log(XdsLogLevel.DEBUG,
|
syncContext.execute(new Runnable() {
|
||||||
"Received endpoint update from xDS client {0}: {1}", xdsClient, update);
|
@Override
|
||||||
if (logger.isLoggable(XdsLogLevel.INFO)) {
|
public void run() {
|
||||||
logger.log(
|
if (shutdown) {
|
||||||
XdsLogLevel.INFO,
|
return;
|
||||||
"Received endpoint update: cluster_name={0}, {1} localities, {2} drop categories",
|
}
|
||||||
update.getClusterName(), update.getLocalityLbEndpointsMap().size(),
|
logger.log(XdsLogLevel.DEBUG,
|
||||||
update.getDropPolicies().size());
|
"Received endpoint update from xDS client {0}: {1}", xdsClient, update);
|
||||||
}
|
if (logger.isLoggable(XdsLogLevel.INFO)) {
|
||||||
lbHelper.updateDropPolicies(update.getDropPolicies());
|
logger.log(XdsLogLevel.INFO, "Received endpoint update: cluster_name={0}, "
|
||||||
Map<Locality, LocalityLbEndpoints> localityLbEndpoints = update.getLocalityLbEndpointsMap();
|
+ "{1} localities, {2} drop categories", update.getClusterName(),
|
||||||
endpointAddresses = new ArrayList<>();
|
update.getLocalityLbEndpointsMap().size(), update.getDropPolicies().size());
|
||||||
prioritizedLocalityWeights = new HashMap<>();
|
}
|
||||||
for (Locality locality : localityLbEndpoints.keySet()) {
|
lbHelper.updateDropPolicies(update.getDropPolicies());
|
||||||
LocalityLbEndpoints localityLbInfo = localityLbEndpoints.get(locality);
|
Map<Locality, LocalityLbEndpoints> localityLbEndpoints =
|
||||||
int priority = localityLbInfo.getPriority();
|
update.getLocalityLbEndpointsMap();
|
||||||
boolean discard = true;
|
endpointAddresses = new ArrayList<>();
|
||||||
for (LbEndpoint endpoint : localityLbInfo.getEndpoints()) {
|
prioritizedLocalityWeights = new HashMap<>();
|
||||||
if (endpoint.isHealthy()) {
|
for (Locality locality : localityLbEndpoints.keySet()) {
|
||||||
discard = false;
|
LocalityLbEndpoints localityLbInfo = localityLbEndpoints.get(locality);
|
||||||
EquivalentAddressGroup eag =
|
int priority = localityLbInfo.getPriority();
|
||||||
AddressFilter.setPathFilter(
|
boolean discard = true;
|
||||||
endpoint.getAddress(),
|
for (LbEndpoint endpoint : localityLbInfo.getEndpoints()) {
|
||||||
Arrays.asList(priorityName(priority), localityName(locality)));
|
if (endpoint.isHealthy()) {
|
||||||
endpointAddresses.add(eag);
|
discard = false;
|
||||||
|
EquivalentAddressGroup eag =
|
||||||
|
AddressFilter.setPathFilter(
|
||||||
|
endpoint.getAddress(),
|
||||||
|
Arrays.asList(priorityName(priority), localityName(locality)));
|
||||||
|
endpointAddresses.add(eag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (discard) {
|
||||||
|
logger.log(XdsLogLevel.INFO, "Discard locality {0} with 0 healthy endpoints");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!prioritizedLocalityWeights.containsKey(priority)) {
|
||||||
|
prioritizedLocalityWeights.put(priority, new HashMap<Locality, Integer>());
|
||||||
|
}
|
||||||
|
prioritizedLocalityWeights.get(priority).put(
|
||||||
|
locality, localityLbInfo.getLocalityWeight());
|
||||||
|
}
|
||||||
|
if (prioritizedLocalityWeights.isEmpty()) {
|
||||||
|
propagateResourceError(
|
||||||
|
Status.UNAVAILABLE.withDescription("No usable priority/locality/endpoint"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (lb == null) {
|
||||||
|
lb = lbRegistry.getProvider(PRIORITY_POLICY_NAME).newLoadBalancer(lbHelper);
|
||||||
|
}
|
||||||
|
if (localityPickingPolicy != null && endpointPickingPolicy != null) {
|
||||||
|
PriorityLbConfig config = generatePriorityLbConfig(cluster, edsServiceName,
|
||||||
|
lrsServerName, localityPickingPolicy, endpointPickingPolicy, lbRegistry,
|
||||||
|
prioritizedLocalityWeights);
|
||||||
|
// TODO(chengyuanzhang): to be deleted after migrating to use XdsClient API.
|
||||||
|
Attributes attributes;
|
||||||
|
if (lrsServerName != null) {
|
||||||
|
attributes =
|
||||||
|
resolvedAddresses.getAttributes().toBuilder()
|
||||||
|
.set(XdsAttributes.ATTR_CLUSTER_SERVICE_LOAD_STATS_STORE, loadStatsStore)
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
attributes = resolvedAddresses.getAttributes();
|
||||||
|
}
|
||||||
|
lb.handleResolvedAddresses(
|
||||||
|
resolvedAddresses.toBuilder()
|
||||||
|
.setAddresses(endpointAddresses)
|
||||||
|
.setAttributes(attributes)
|
||||||
|
.setLoadBalancingPolicyConfig(config)
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (discard) {
|
});
|
||||||
logger.log(XdsLogLevel.INFO, "Discard locality {0} with 0 healthy endpoints");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!prioritizedLocalityWeights.containsKey(priority)) {
|
|
||||||
prioritizedLocalityWeights.put(priority, new HashMap<Locality, Integer>());
|
|
||||||
}
|
|
||||||
prioritizedLocalityWeights.get(priority).put(
|
|
||||||
locality, localityLbInfo.getLocalityWeight());
|
|
||||||
}
|
|
||||||
if (prioritizedLocalityWeights.isEmpty()) {
|
|
||||||
propagateResourceError(
|
|
||||||
Status.UNAVAILABLE.withDescription("No usable priority/locality/endpoint"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (lb == null) {
|
|
||||||
lb = lbRegistry.getProvider(PRIORITY_POLICY_NAME).newLoadBalancer(lbHelper);
|
|
||||||
}
|
|
||||||
if (localityPickingPolicy != null && endpointPickingPolicy != null) {
|
|
||||||
PriorityLbConfig config = generatePriorityLbConfig(cluster, edsServiceName,
|
|
||||||
lrsServerName, localityPickingPolicy, endpointPickingPolicy, lbRegistry,
|
|
||||||
prioritizedLocalityWeights);
|
|
||||||
// TODO(chengyuanzhang): to be deleted after migrating to use XdsClient API.
|
|
||||||
Attributes attributes;
|
|
||||||
if (lrsServerName != null) {
|
|
||||||
attributes =
|
|
||||||
resolvedAddresses.getAttributes().toBuilder()
|
|
||||||
.set(XdsAttributes.ATTR_CLUSTER_SERVICE_LOAD_STATS_STORE, loadStatsStore)
|
|
||||||
.build();
|
|
||||||
} else {
|
|
||||||
attributes = resolvedAddresses.getAttributes();
|
|
||||||
}
|
|
||||||
lb.handleResolvedAddresses(
|
|
||||||
resolvedAddresses.toBuilder()
|
|
||||||
.setAddresses(endpointAddresses)
|
|
||||||
.setAttributes(attributes)
|
|
||||||
.setLoadBalancingPolicyConfig(config)
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResourceDoesNotExist(String resourceName) {
|
public void onResourceDoesNotExist(final String resourceName) {
|
||||||
logger.log(XdsLogLevel.INFO, "Resource {0} is unavailable", resourceName);
|
syncContext.execute(new Runnable() {
|
||||||
propagateResourceError(
|
@Override
|
||||||
Status.UNAVAILABLE.withDescription("Resource " + resourceName + " is unavailable"));
|
public void run() {
|
||||||
|
if (shutdown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.log(XdsLogLevel.INFO, "Resource {0} is unavailable", resourceName);
|
||||||
|
propagateResourceError(Status.UNAVAILABLE.withDescription(
|
||||||
|
"Resource " + resourceName + " is unavailable"));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Status error) {
|
public void onError(final Status error) {
|
||||||
logger.log(
|
syncContext.execute(new Runnable() {
|
||||||
XdsLogLevel.WARNING, "Received error from xDS client {0}: {1}", xdsClient, error);
|
@Override
|
||||||
if (lb == null) {
|
public void run() {
|
||||||
lbHelper.helper.updateBalancingState(TRANSIENT_FAILURE, new ErrorPicker(error));
|
if (shutdown) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
logger.log(
|
||||||
|
XdsLogLevel.WARNING, "Received error from xDS client {0}: {1}", xdsClient, error);
|
||||||
|
if (lb == null) {
|
||||||
|
lbHelper.helper.updateBalancingState(TRANSIENT_FAILURE, new ErrorPicker(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void propagateResourceError(Status error) {
|
private void propagateResourceError(Status error) {
|
||||||
|
|
|
||||||
|
|
@ -430,6 +430,7 @@ final class XdsNameResolver extends NameResolver {
|
||||||
.setServiceConfig(emptyServiceConfig)
|
.setServiceConfig(emptyServiceConfig)
|
||||||
// let channel take action for no config selector
|
// let channel take action for no config selector
|
||||||
.build();
|
.build();
|
||||||
|
private boolean stopped;
|
||||||
private Set<String> existingClusters;
|
private Set<String> existingClusters;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String rdsResource;
|
private String rdsResource;
|
||||||
|
|
@ -438,38 +439,62 @@ final class XdsNameResolver extends NameResolver {
|
||||||
private long httpMaxStreamDurationNano;
|
private long httpMaxStreamDurationNano;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(LdsUpdate update) {
|
public void onChanged(final LdsUpdate update) {
|
||||||
logger.log(XdsLogLevel.INFO, "Receive LDS resource update: {0}", update);
|
syncContext.execute(new Runnable() {
|
||||||
httpMaxStreamDurationNano = update.getHttpMaxStreamDurationNano();
|
@Override
|
||||||
List<VirtualHost> virtualHosts = update.getVirtualHosts();
|
public void run() {
|
||||||
String rdsName = update.getRdsName();
|
if (stopped) {
|
||||||
if (rdsName != null && rdsName.equals(rdsResource)) {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
logger.log(XdsLogLevel.INFO, "Receive LDS resource update: {0}", update);
|
||||||
cleanUpRdsWatcher();
|
httpMaxStreamDurationNano = update.getHttpMaxStreamDurationNano();
|
||||||
if (virtualHosts != null) {
|
List<VirtualHost> virtualHosts = update.getVirtualHosts();
|
||||||
updateRoutes(virtualHosts);
|
String rdsName = update.getRdsName();
|
||||||
} else {
|
if (rdsName != null && rdsName.equals(rdsResource)) {
|
||||||
rdsResource = rdsName;
|
return;
|
||||||
rdsWatcher = new RdsResourceWatcherImpl();
|
}
|
||||||
logger.log(XdsLogLevel.INFO, "Start watching RDS resource {0}", rdsResource);
|
cleanUpRdsWatcher();
|
||||||
xdsClient.watchRdsResource(rdsResource, rdsWatcher);
|
if (virtualHosts != null) {
|
||||||
}
|
updateRoutes(virtualHosts);
|
||||||
|
} else {
|
||||||
|
rdsResource = rdsName;
|
||||||
|
rdsWatcher = new RdsResourceWatcherImpl();
|
||||||
|
logger.log(XdsLogLevel.INFO, "Start watching RDS resource {0}", rdsResource);
|
||||||
|
xdsClient.watchRdsResource(rdsResource, rdsWatcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Status error) {
|
public void onError(final Status error) {
|
||||||
logger.log(
|
syncContext.execute(new Runnable() {
|
||||||
XdsLogLevel.WARNING,
|
@Override
|
||||||
"Received error from xDS client {0}: {1}", xdsClient, error.getDescription());
|
public void run() {
|
||||||
listener.onError(error);
|
if (stopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.log(
|
||||||
|
XdsLogLevel.WARNING,
|
||||||
|
"Received error from xDS client {0}: {1}", xdsClient, error.getDescription());
|
||||||
|
listener.onError(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResourceDoesNotExist(String resourceName) {
|
public void onResourceDoesNotExist(final String resourceName) {
|
||||||
logger.log(XdsLogLevel.INFO, "LDS resource {0} unavailable", resourceName);
|
syncContext.execute(new Runnable() {
|
||||||
cleanUpRdsWatcher();
|
@Override
|
||||||
listener.onResult(emptyResult);
|
public void run() {
|
||||||
|
if (stopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.log(XdsLogLevel.INFO, "LDS resource {0} unavailable", resourceName);
|
||||||
|
cleanUpRdsWatcher();
|
||||||
|
listener.onResult(emptyResult);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void start() {
|
private void start() {
|
||||||
|
|
@ -479,6 +504,7 @@ final class XdsNameResolver extends NameResolver {
|
||||||
|
|
||||||
private void stop() {
|
private void stop() {
|
||||||
logger.log(XdsLogLevel.INFO, "Stop watching LDS resource {0}", authority);
|
logger.log(XdsLogLevel.INFO, "Stop watching LDS resource {0}", authority);
|
||||||
|
stopped = true;
|
||||||
cleanUpRdsWatcher();
|
cleanUpRdsWatcher();
|
||||||
xdsClient.cancelLdsResourceWatch(authority, this);
|
xdsClient.cancelLdsResourceWatch(authority, this);
|
||||||
}
|
}
|
||||||
|
|
@ -550,22 +576,46 @@ final class XdsNameResolver extends NameResolver {
|
||||||
private class RdsResourceWatcherImpl implements RdsResourceWatcher {
|
private class RdsResourceWatcherImpl implements RdsResourceWatcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(RdsUpdate update) {
|
public void onChanged(final RdsUpdate update) {
|
||||||
updateRoutes(update.getVirtualHosts());
|
syncContext.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (RdsResourceWatcherImpl.this != rdsWatcher) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateRoutes(update.getVirtualHosts());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Status error) {
|
public void onError(final Status error) {
|
||||||
logger.log(
|
syncContext.execute(new Runnable() {
|
||||||
XdsLogLevel.WARNING,
|
@Override
|
||||||
"Received error from xDS client {0}: {1}", xdsClient, error.getDescription());
|
public void run() {
|
||||||
listener.onError(error);
|
if (RdsResourceWatcherImpl.this != rdsWatcher) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.log(
|
||||||
|
XdsLogLevel.WARNING,
|
||||||
|
"Received error from xDS client {0}: {1}", xdsClient, error.getDescription());
|
||||||
|
listener.onError(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResourceDoesNotExist(String resourceName) {
|
public void onResourceDoesNotExist(final String resourceName) {
|
||||||
logger.log(XdsLogLevel.INFO, "RDS resource {0} unavailable", resourceName);
|
syncContext.execute(new Runnable() {
|
||||||
listener.onResult(emptyResult);
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (RdsResourceWatcherImpl.this != rdsWatcher) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.log(XdsLogLevel.INFO, "RDS resource {0} unavailable", resourceName);
|
||||||
|
listener.onResult(emptyResult);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -467,6 +467,11 @@ public class CdsLoadBalancerTest {
|
||||||
throw new UnsupportedOperationException("should not be called");
|
throw new UnsupportedOperationException("should not be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SynchronizationContext getSynchronizationContext() {
|
||||||
|
return syncContext;
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public NameResolver.Factory getNameResolverFactory() {
|
public NameResolver.Factory getNameResolverFactory() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue