mirror of https://github.com/grpc/grpc-java.git
Xds client split (#11484)
This commit is contained in:
parent
ee3ffef3ee
commit
d034a56cb0
|
@ -39,6 +39,8 @@ import io.grpc.xds.client.XdsClient.ResourceMetadata;
|
|||
import io.grpc.xds.client.XdsClient.ResourceMetadata.ResourceMetadataStatus;
|
||||
import io.grpc.xds.client.XdsClient.ResourceMetadata.UpdateFailureState;
|
||||
import io.grpc.xds.client.XdsResourceType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -117,43 +119,58 @@ public final class CsdsService implements BindableService {
|
|||
|
||||
private boolean handleRequest(
|
||||
ClientStatusRequest request, StreamObserver<ClientStatusResponse> responseObserver) {
|
||||
StatusException error;
|
||||
try {
|
||||
responseObserver.onNext(getConfigDumpForRequest(request));
|
||||
return true;
|
||||
} catch (StatusException e) {
|
||||
error = e;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
logger.log(Level.FINE, "Server interrupted while building CSDS config dump", e);
|
||||
error = Status.ABORTED.withDescription("Thread interrupted").withCause(e).asException();
|
||||
} catch (RuntimeException e) {
|
||||
logger.log(Level.WARNING, "Unexpected error while building CSDS config dump", e);
|
||||
error =
|
||||
Status.INTERNAL.withDescription("Unexpected internal error").withCause(e).asException();
|
||||
StatusException error = null;
|
||||
|
||||
if (request.getNodeMatchersCount() > 0) {
|
||||
error = new StatusException(
|
||||
Status.INVALID_ARGUMENT.withDescription("node_matchers not supported"));
|
||||
} else {
|
||||
List<String> targets = xdsClientPoolFactory.getTargets();
|
||||
List<ClientConfig> clientConfigs = new ArrayList<>(targets.size());
|
||||
|
||||
for (int i = 0; i < targets.size() && error == null; i++) {
|
||||
try {
|
||||
ClientConfig clientConfig = getConfigForRequest(targets.get(i));
|
||||
if (clientConfig != null) {
|
||||
clientConfigs.add(clientConfig);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
logger.log(Level.FINE, "Server interrupted while building CSDS config dump", e);
|
||||
error = Status.ABORTED.withDescription("Thread interrupted").withCause(e).asException();
|
||||
} catch (RuntimeException e) {
|
||||
logger.log(Level.WARNING, "Unexpected error while building CSDS config dump", e);
|
||||
error = Status.INTERNAL.withDescription("Unexpected internal error").withCause(e)
|
||||
.asException();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
responseObserver.onNext(getStatusResponse(clientConfigs));
|
||||
} catch (RuntimeException e) {
|
||||
logger.log(Level.WARNING, "Unexpected error while processing CSDS config dump", e);
|
||||
error = Status.INTERNAL.withDescription("Unexpected internal error").withCause(e)
|
||||
.asException();
|
||||
}
|
||||
}
|
||||
|
||||
if (error == null) {
|
||||
return true; // All clients reported without error
|
||||
}
|
||||
responseObserver.onError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
private ClientStatusResponse getConfigDumpForRequest(ClientStatusRequest request)
|
||||
throws StatusException, InterruptedException {
|
||||
if (request.getNodeMatchersCount() > 0) {
|
||||
throw new StatusException(
|
||||
Status.INVALID_ARGUMENT.withDescription("node_matchers not supported"));
|
||||
}
|
||||
|
||||
ObjectPool<XdsClient> xdsClientPool = xdsClientPoolFactory.get();
|
||||
private ClientConfig getConfigForRequest(String target) throws InterruptedException {
|
||||
ObjectPool<XdsClient> xdsClientPool = xdsClientPoolFactory.get(target);
|
||||
if (xdsClientPool == null) {
|
||||
return ClientStatusResponse.getDefaultInstance();
|
||||
return null;
|
||||
}
|
||||
|
||||
XdsClient xdsClient = null;
|
||||
try {
|
||||
xdsClient = xdsClientPool.getObject();
|
||||
return ClientStatusResponse.newBuilder()
|
||||
.addConfig(getClientConfigForXdsClient(xdsClient))
|
||||
.build();
|
||||
return getClientConfigForXdsClient(xdsClient, target);
|
||||
} finally {
|
||||
if (xdsClient != null) {
|
||||
xdsClientPool.returnObject(xdsClient);
|
||||
|
@ -161,9 +178,18 @@ public final class CsdsService implements BindableService {
|
|||
}
|
||||
}
|
||||
|
||||
private ClientStatusResponse getStatusResponse(List<ClientConfig> clientConfigs) {
|
||||
if (clientConfigs.isEmpty()) {
|
||||
return ClientStatusResponse.getDefaultInstance();
|
||||
}
|
||||
return ClientStatusResponse.newBuilder().addAllConfig(clientConfigs).build();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static ClientConfig getClientConfigForXdsClient(XdsClient xdsClient) throws InterruptedException {
|
||||
static ClientConfig getClientConfigForXdsClient(XdsClient xdsClient, String target)
|
||||
throws InterruptedException {
|
||||
ClientConfig.Builder builder = ClientConfig.newBuilder()
|
||||
.setClientScope(target)
|
||||
.setNode(xdsClient.getBootstrapInfo().node().toEnvoyProtoNode());
|
||||
|
||||
Map<XdsResourceType<?>, Map<String, ResourceMetadata>> metadataByType =
|
||||
|
|
|
@ -36,6 +36,6 @@ public final class InternalSharedXdsClientPoolProvider {
|
|||
|
||||
public static ObjectPool<XdsClient> getOrCreate(String target)
|
||||
throws XdsInitializationException {
|
||||
return SharedXdsClientPoolProvider.getDefaultProvider().getOrCreate();
|
||||
return SharedXdsClientPoolProvider.getDefaultProvider().getOrCreate(target);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import static io.grpc.xds.GrpcXdsTransportFactory.DEFAULT_XDS_TRANSPORT_FACTORY;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import io.grpc.internal.ExponentialBackoffPolicy;
|
||||
import io.grpc.internal.GrpcUtil;
|
||||
import io.grpc.internal.ObjectPool;
|
||||
|
@ -32,6 +33,7 @@ import io.grpc.xds.client.XdsClientImpl;
|
|||
import io.grpc.xds.client.XdsInitializationException;
|
||||
import io.grpc.xds.internal.security.TlsContextManagerImpl;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.logging.Level;
|
||||
|
@ -53,7 +55,7 @@ final class SharedXdsClientPoolProvider implements XdsClientPoolFactory {
|
|||
private final Bootstrapper bootstrapper;
|
||||
private final Object lock = new Object();
|
||||
private final AtomicReference<Map<String, ?>> bootstrapOverride = new AtomicReference<>();
|
||||
private volatile ObjectPool<XdsClient> xdsClientPool;
|
||||
private final Map<String, ObjectPool<XdsClient>> targetToXdsClientMap = new ConcurrentHashMap<>();
|
||||
|
||||
SharedXdsClientPoolProvider() {
|
||||
this(new GrpcBootstrapperImpl());
|
||||
|
@ -75,16 +77,16 @@ final class SharedXdsClientPoolProvider implements XdsClientPoolFactory {
|
|||
|
||||
@Override
|
||||
@Nullable
|
||||
public ObjectPool<XdsClient> get() {
|
||||
return xdsClientPool;
|
||||
public ObjectPool<XdsClient> get(String target) {
|
||||
return targetToXdsClientMap.get(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPool<XdsClient> getOrCreate() throws XdsInitializationException {
|
||||
ObjectPool<XdsClient> ref = xdsClientPool;
|
||||
public ObjectPool<XdsClient> getOrCreate(String target) throws XdsInitializationException {
|
||||
ObjectPool<XdsClient> ref = targetToXdsClientMap.get(target);
|
||||
if (ref == null) {
|
||||
synchronized (lock) {
|
||||
ref = xdsClientPool;
|
||||
ref = targetToXdsClientMap.get(target);
|
||||
if (ref == null) {
|
||||
BootstrapInfo bootstrapInfo;
|
||||
Map<String, ?> rawBootstrap = bootstrapOverride.get();
|
||||
|
@ -96,13 +98,20 @@ final class SharedXdsClientPoolProvider implements XdsClientPoolFactory {
|
|||
if (bootstrapInfo.servers().isEmpty()) {
|
||||
throw new XdsInitializationException("No xDS server provided");
|
||||
}
|
||||
ref = xdsClientPool = new RefCountedXdsClientObjectPool(bootstrapInfo);
|
||||
ref = new RefCountedXdsClientObjectPool(bootstrapInfo, target);
|
||||
targetToXdsClientMap.put(target, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<String> getTargets() {
|
||||
return ImmutableList.copyOf(targetToXdsClientMap.keySet());
|
||||
}
|
||||
|
||||
|
||||
private static class SharedXdsClientPoolProviderHolder {
|
||||
private static final SharedXdsClientPoolProvider instance = new SharedXdsClientPoolProvider();
|
||||
}
|
||||
|
@ -110,7 +119,11 @@ final class SharedXdsClientPoolProvider implements XdsClientPoolFactory {
|
|||
@ThreadSafe
|
||||
@VisibleForTesting
|
||||
static class RefCountedXdsClientObjectPool implements ObjectPool<XdsClient> {
|
||||
|
||||
private static final ExponentialBackoffPolicy.Provider BACKOFF_POLICY_PROVIDER =
|
||||
new ExponentialBackoffPolicy.Provider();
|
||||
private final BootstrapInfo bootstrapInfo;
|
||||
private final String target; // The target associated with the xDS client.
|
||||
private final Object lock = new Object();
|
||||
@GuardedBy("lock")
|
||||
private ScheduledExecutorService scheduler;
|
||||
|
@ -120,8 +133,9 @@ final class SharedXdsClientPoolProvider implements XdsClientPoolFactory {
|
|||
private int refCount;
|
||||
|
||||
@VisibleForTesting
|
||||
RefCountedXdsClientObjectPool(BootstrapInfo bootstrapInfo) {
|
||||
RefCountedXdsClientObjectPool(BootstrapInfo bootstrapInfo, String target) {
|
||||
this.bootstrapInfo = checkNotNull(bootstrapInfo);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -136,7 +150,7 @@ final class SharedXdsClientPoolProvider implements XdsClientPoolFactory {
|
|||
DEFAULT_XDS_TRANSPORT_FACTORY,
|
||||
bootstrapInfo,
|
||||
scheduler,
|
||||
new ExponentialBackoffPolicy.Provider(),
|
||||
BACKOFF_POLICY_PROVIDER,
|
||||
GrpcUtil.STOPWATCH_SUPPLIER,
|
||||
TimeProvider.SYSTEM_TIME_PROVIDER,
|
||||
MessagePrinter.INSTANCE,
|
||||
|
@ -167,5 +181,10 @@ final class SharedXdsClientPoolProvider implements XdsClientPoolFactory {
|
|||
return xdsClient;
|
||||
}
|
||||
}
|
||||
|
||||
public String getTarget() {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package io.grpc.xds;
|
|||
import io.grpc.internal.ObjectPool;
|
||||
import io.grpc.xds.client.XdsClient;
|
||||
import io.grpc.xds.client.XdsInitializationException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -26,7 +27,9 @@ interface XdsClientPoolFactory {
|
|||
void setBootstrapOverride(Map<String, ?> bootstrap);
|
||||
|
||||
@Nullable
|
||||
ObjectPool<XdsClient> get();
|
||||
ObjectPool<XdsClient> get(String target);
|
||||
|
||||
ObjectPool<XdsClient> getOrCreate() throws XdsInitializationException;
|
||||
ObjectPool<XdsClient> getOrCreate(String target) throws XdsInitializationException;
|
||||
|
||||
List<String> getTargets();
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ import io.grpc.xds.client.XdsClient;
|
|||
import io.grpc.xds.client.XdsClient.ResourceWatcher;
|
||||
import io.grpc.xds.client.XdsLogger;
|
||||
import io.grpc.xds.client.XdsLogger.XdsLogLevel;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -104,6 +105,7 @@ final class XdsNameResolver extends NameResolver {
|
|||
private final XdsLogger logger;
|
||||
@Nullable
|
||||
private final String targetAuthority;
|
||||
private final String target;
|
||||
private final String serviceAuthority;
|
||||
// Encoded version of the service authority as per
|
||||
// https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.
|
||||
|
@ -133,23 +135,24 @@ final class XdsNameResolver extends NameResolver {
|
|||
private boolean receivedConfig;
|
||||
|
||||
XdsNameResolver(
|
||||
@Nullable String targetAuthority, String name, @Nullable String overrideAuthority,
|
||||
URI targetUri, String name, @Nullable String overrideAuthority,
|
||||
ServiceConfigParser serviceConfigParser,
|
||||
SynchronizationContext syncContext, ScheduledExecutorService scheduler,
|
||||
@Nullable Map<String, ?> bootstrapOverride) {
|
||||
this(targetAuthority, name, overrideAuthority, serviceConfigParser, syncContext, scheduler,
|
||||
SharedXdsClientPoolProvider.getDefaultProvider(), ThreadSafeRandomImpl.instance,
|
||||
FilterRegistry.getDefaultRegistry(), bootstrapOverride);
|
||||
this(targetUri, targetUri.getAuthority(), name, overrideAuthority, serviceConfigParser,
|
||||
syncContext, scheduler, SharedXdsClientPoolProvider.getDefaultProvider(),
|
||||
ThreadSafeRandomImpl.instance, FilterRegistry.getDefaultRegistry(), bootstrapOverride);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
XdsNameResolver(
|
||||
@Nullable String targetAuthority, String name, @Nullable String overrideAuthority,
|
||||
ServiceConfigParser serviceConfigParser,
|
||||
URI targetUri, @Nullable String targetAuthority, String name,
|
||||
@Nullable String overrideAuthority, ServiceConfigParser serviceConfigParser,
|
||||
SynchronizationContext syncContext, ScheduledExecutorService scheduler,
|
||||
XdsClientPoolFactory xdsClientPoolFactory, ThreadSafeRandom random,
|
||||
FilterRegistry filterRegistry, @Nullable Map<String, ?> bootstrapOverride) {
|
||||
this.targetAuthority = targetAuthority;
|
||||
target = targetUri.toString();
|
||||
|
||||
// The name might have multiple slashes so encode it before verifying.
|
||||
serviceAuthority = checkNotNull(name, "name");
|
||||
|
@ -180,7 +183,7 @@ final class XdsNameResolver extends NameResolver {
|
|||
public void start(Listener2 listener) {
|
||||
this.listener = checkNotNull(listener, "listener");
|
||||
try {
|
||||
xdsClientPool = xdsClientPoolFactory.getOrCreate();
|
||||
xdsClientPool = xdsClientPoolFactory.getOrCreate(target);
|
||||
} catch (Exception e) {
|
||||
listener.onError(
|
||||
Status.UNAVAILABLE.withDescription("Failed to initialize xDS").withCause(e));
|
||||
|
|
|
@ -78,7 +78,7 @@ public final class XdsNameResolverProvider extends NameResolverProvider {
|
|||
targetUri);
|
||||
String name = targetPath.substring(1);
|
||||
return new XdsNameResolver(
|
||||
targetUri.getAuthority(), name, args.getOverrideAuthority(),
|
||||
targetUri, name, args.getOverrideAuthority(),
|
||||
args.getServiceConfigParser(), args.getSynchronizationContext(),
|
||||
args.getScheduledExecutorService(),
|
||||
bootstrapOverride);
|
||||
|
|
|
@ -171,7 +171,7 @@ final class XdsServerWrapper extends Server {
|
|||
|
||||
private void internalStart() {
|
||||
try {
|
||||
xdsClientPool = xdsClientPoolFactory.getOrCreate();
|
||||
xdsClientPool = xdsClientPoolFactory.getOrCreate("");
|
||||
} catch (Exception e) {
|
||||
StatusException statusException = Status.UNAVAILABLE.withDescription(
|
||||
"Failed to initialize xDS").withCause(e).asException();
|
||||
|
|
|
@ -54,6 +54,7 @@ import io.grpc.xds.client.XdsClient;
|
|||
import io.grpc.xds.client.XdsClient.ResourceMetadata;
|
||||
import io.grpc.xds.client.XdsClient.ResourceMetadata.ResourceMetadataStatus;
|
||||
import io.grpc.xds.client.XdsResourceType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -85,6 +86,7 @@ public class CsdsServiceTest {
|
|||
private static final XdsResourceType<?> CDS = XdsClusterResource.getInstance();
|
||||
private static final XdsResourceType<?> RDS = XdsRouteConfigureResource.getInstance();
|
||||
private static final XdsResourceType<?> EDS = XdsEndpointResource.getInstance();
|
||||
public static final String FAKE_CLIENT_SCOPE = "fake";
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public static class ServiceTests {
|
||||
|
@ -198,13 +200,13 @@ public class CsdsServiceTest {
|
|||
|
||||
@Override
|
||||
@Nullable
|
||||
public ObjectPool<XdsClient> get() {
|
||||
public ObjectPool<XdsClient> get(String target) {
|
||||
// xDS client not ready on the first call, then becomes ready.
|
||||
if (!calledOnce) {
|
||||
calledOnce = true;
|
||||
return null;
|
||||
} else {
|
||||
return super.get();
|
||||
return super.get(target);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -267,11 +269,51 @@ public class CsdsServiceTest {
|
|||
assertThat(responseObserver.getError()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleXdsClients() {
|
||||
FakeXdsClient xdsClient1 = new FakeXdsClient();
|
||||
FakeXdsClient xdsClient2 = new FakeXdsClient();
|
||||
Map<String, XdsClient> clientMap = new HashMap<>();
|
||||
clientMap.put("target1", xdsClient1);
|
||||
clientMap.put("target2", xdsClient2);
|
||||
FakeXdsClientPoolFactory factory = new FakeXdsClientPoolFactory(clientMap);
|
||||
CsdsService csdsService = new CsdsService(factory);
|
||||
grpcServerRule.getServiceRegistry().addService(csdsService);
|
||||
|
||||
StreamRecorder<ClientStatusResponse> responseObserver = StreamRecorder.create();
|
||||
StreamObserver<ClientStatusRequest> requestObserver =
|
||||
csdsAsyncStub.streamClientStatus(responseObserver);
|
||||
|
||||
requestObserver.onNext(REQUEST);
|
||||
requestObserver.onCompleted();
|
||||
|
||||
List<ClientStatusResponse> responses = responseObserver.getValues();
|
||||
assertThat(responses).hasSize(1);
|
||||
Collection<String> targets = verifyMultiResponse(responses.get(0), 2);
|
||||
assertThat(targets).containsExactly("target1", "target2");
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
|
||||
private void verifyResponse(ClientStatusResponse response) {
|
||||
assertThat(response.getConfigCount()).isEqualTo(1);
|
||||
ClientConfig clientConfig = response.getConfig(0);
|
||||
verifyClientConfigNode(clientConfig);
|
||||
verifyClientConfigNoResources(XDS_CLIENT_NO_RESOURCES, clientConfig);
|
||||
assertThat(clientConfig.getClientScope()).isEmpty();
|
||||
}
|
||||
|
||||
private Collection<String> verifyMultiResponse(ClientStatusResponse response, int numExpected) {
|
||||
assertThat(response.getConfigCount()).isEqualTo(numExpected);
|
||||
|
||||
List<String> clientScopes = new ArrayList<>();
|
||||
for (int i = 0; i < numExpected; i++) {
|
||||
ClientConfig clientConfig = response.getConfig(i);
|
||||
verifyClientConfigNode(clientConfig);
|
||||
verifyClientConfigNoResources(XDS_CLIENT_NO_RESOURCES, clientConfig);
|
||||
clientScopes.add(clientConfig.getClientScope());
|
||||
}
|
||||
|
||||
return clientScopes;
|
||||
}
|
||||
|
||||
private void verifyRequestInvalidResponseStatus(Status status) {
|
||||
|
@ -350,9 +392,11 @@ public class CsdsServiceTest {
|
|||
);
|
||||
}
|
||||
};
|
||||
ClientConfig clientConfig = CsdsService.getClientConfigForXdsClient(fakeXdsClient);
|
||||
ClientConfig clientConfig = CsdsService.getClientConfigForXdsClient(fakeXdsClient,
|
||||
FAKE_CLIENT_SCOPE);
|
||||
|
||||
verifyClientConfigNode(clientConfig);
|
||||
assertThat(clientConfig.getClientScope()).isEqualTo(FAKE_CLIENT_SCOPE);
|
||||
|
||||
// Minimal verification to confirm that the data/metadata XdsClient provides,
|
||||
// is propagated to the correct resource types.
|
||||
|
@ -390,9 +434,11 @@ public class CsdsServiceTest {
|
|||
|
||||
@Test
|
||||
public void getClientConfigForXdsClient_noSubscribedResources() throws InterruptedException {
|
||||
ClientConfig clientConfig = CsdsService.getClientConfigForXdsClient(XDS_CLIENT_NO_RESOURCES);
|
||||
ClientConfig clientConfig =
|
||||
CsdsService.getClientConfigForXdsClient(XDS_CLIENT_NO_RESOURCES, FAKE_CLIENT_SCOPE);
|
||||
verifyClientConfigNode(clientConfig);
|
||||
verifyClientConfigNoResources(XDS_CLIENT_NO_RESOURCES, clientConfig);
|
||||
assertThat(clientConfig.getClientScope()).isEqualTo(FAKE_CLIENT_SCOPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,22 +506,35 @@ public class CsdsServiceTest {
|
|||
public Map<String, XdsResourceType<?>> getSubscribedResourceTypesWithTypeUrl() {
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class FakeXdsClientPoolFactory implements XdsClientPoolFactory {
|
||||
@Nullable private final XdsClient xdsClient;
|
||||
private final Map<String, XdsClient> xdsClientMap = new HashMap<>();
|
||||
private boolean isOldStyle
|
||||
;
|
||||
|
||||
private FakeXdsClientPoolFactory(@Nullable XdsClient xdsClient) {
|
||||
this.xdsClient = xdsClient;
|
||||
if (xdsClient != null) {
|
||||
xdsClientMap.put("", xdsClient);
|
||||
}
|
||||
isOldStyle = true;
|
||||
}
|
||||
|
||||
private FakeXdsClientPoolFactory(Map<String,XdsClient> xdsClientMap) {
|
||||
this.xdsClientMap.putAll(xdsClientMap);
|
||||
isOldStyle = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ObjectPool<XdsClient> get() {
|
||||
public ObjectPool<XdsClient> get(String target) {
|
||||
String targetToUse = isOldStyle ? "" : target;
|
||||
|
||||
return new ObjectPool<XdsClient>() {
|
||||
@Override
|
||||
public XdsClient getObject() {
|
||||
return xdsClient;
|
||||
return xdsClientMap.get(targetToUse);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -485,13 +544,18 @@ public class CsdsServiceTest {
|
|||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTargets() {
|
||||
return new ArrayList<>(xdsClientMap.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBootstrapOverride(Map<String, ?> bootstrap) {
|
||||
throw new UnsupportedOperationException("Should not be called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPool<XdsClient> getOrCreate() {
|
||||
public ObjectPool<XdsClient> getOrCreate(String target) {
|
||||
throw new UnsupportedOperationException("Should not be called");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -340,8 +340,7 @@ public abstract class GrpcXdsClientImplTestBase {
|
|||
}
|
||||
};
|
||||
|
||||
xdsServerInfo = ServerInfo.create(SERVER_URI, CHANNEL_CREDENTIALS,
|
||||
ignoreResourceDeletion());
|
||||
xdsServerInfo = ServerInfo.create(SERVER_URI, CHANNEL_CREDENTIALS, ignoreResourceDeletion());
|
||||
BootstrapInfo bootstrapInfo =
|
||||
Bootstrapper.BootstrapInfo.builder()
|
||||
.servers(Collections.singletonList(xdsServerInfo))
|
||||
|
@ -2974,6 +2973,7 @@ public abstract class GrpcXdsClientImplTestBase {
|
|||
anotherWatcher, fakeWatchClock.getScheduledExecutorService());
|
||||
verifyResourceMetadataRequested(CDS, CDS_RESOURCE);
|
||||
verifyResourceMetadataRequested(CDS, anotherCdsResource);
|
||||
|
||||
DiscoveryRpcCall call = resourceDiscoveryCalls.poll();
|
||||
call.verifyRequest(CDS, Arrays.asList(CDS_RESOURCE, anotherCdsResource), "", "", NODE);
|
||||
assertThat(fakeWatchClock.runDueTasks()).isEqualTo(2);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package io.grpc.xds;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.AdditionalAnswers.delegatesTo;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -144,7 +145,8 @@ public class GrpcXdsClientImplV3Test extends GrpcXdsClientImplTestBase {
|
|||
assertThat(adsEnded.get()).isTrue(); // ensure previous call was ended
|
||||
adsEnded.set(false);
|
||||
@SuppressWarnings("unchecked")
|
||||
StreamObserver<DiscoveryRequest> requestObserver = mock(StreamObserver.class);
|
||||
StreamObserver<DiscoveryRequest> requestObserver =
|
||||
mock(StreamObserver.class, delegatesTo(new MockStreamObserver()));
|
||||
DiscoveryRpcCall call = new DiscoveryRpcCallV3(requestObserver, responseObserver);
|
||||
resourceDiscoveryCalls.offer(call);
|
||||
Context.current().addListener(
|
||||
|
@ -874,6 +876,19 @@ public class GrpcXdsClientImplV3Test extends GrpcXdsClientImplTestBase {
|
|||
}
|
||||
return node.equals(argument.getNode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DiscoveryRequestMatcher{"
|
||||
+ "node=" + node
|
||||
+ ", versionInfo='" + versionInfo + '\''
|
||||
+ ", typeUrl='" + typeUrl + '\''
|
||||
+ ", resources=" + resources
|
||||
+ ", responseNonce='" + responseNonce + '\''
|
||||
+ ", errorCode=" + errorCode
|
||||
+ ", errorMessages=" + errorMessages
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -901,4 +916,23 @@ public class GrpcXdsClientImplV3Test extends GrpcXdsClientImplTestBase {
|
|||
return actual.equals(expected);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MockStreamObserver implements StreamObserver<DiscoveryRequest> {
|
||||
private final List<DiscoveryRequest> requests = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onNext(DiscoveryRequest value) {
|
||||
requests.add(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ public class SharedXdsClientPoolProviderTest {
|
|||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
private final Node node = Node.newBuilder().setId("SharedXdsClientPoolProviderTest").build();
|
||||
private static final String DUMMY_TARGET = "dummy";
|
||||
|
||||
@Mock
|
||||
private GrpcBootstrapperImpl bootstrapper;
|
||||
|
@ -63,8 +64,8 @@ public class SharedXdsClientPoolProviderTest {
|
|||
SharedXdsClientPoolProvider provider = new SharedXdsClientPoolProvider(bootstrapper);
|
||||
thrown.expect(XdsInitializationException.class);
|
||||
thrown.expectMessage("No xDS server provided");
|
||||
provider.getOrCreate();
|
||||
assertThat(provider.get()).isNull();
|
||||
provider.getOrCreate(DUMMY_TARGET);
|
||||
assertThat(provider.get(DUMMY_TARGET)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -75,12 +76,12 @@ public class SharedXdsClientPoolProviderTest {
|
|||
when(bootstrapper.bootstrap()).thenReturn(bootstrapInfo);
|
||||
|
||||
SharedXdsClientPoolProvider provider = new SharedXdsClientPoolProvider(bootstrapper);
|
||||
assertThat(provider.get()).isNull();
|
||||
ObjectPool<XdsClient> xdsClientPool = provider.getOrCreate();
|
||||
assertThat(provider.get(DUMMY_TARGET)).isNull();
|
||||
ObjectPool<XdsClient> xdsClientPool = provider.getOrCreate(DUMMY_TARGET);
|
||||
verify(bootstrapper).bootstrap();
|
||||
assertThat(provider.getOrCreate()).isSameInstanceAs(xdsClientPool);
|
||||
assertThat(provider.get()).isNotNull();
|
||||
assertThat(provider.get()).isSameInstanceAs(xdsClientPool);
|
||||
assertThat(provider.getOrCreate(DUMMY_TARGET)).isSameInstanceAs(xdsClientPool);
|
||||
assertThat(provider.get(DUMMY_TARGET)).isNotNull();
|
||||
assertThat(provider.get(DUMMY_TARGET)).isSameInstanceAs(xdsClientPool);
|
||||
verifyNoMoreInteractions(bootstrapper);
|
||||
}
|
||||
|
||||
|
@ -90,7 +91,7 @@ public class SharedXdsClientPoolProviderTest {
|
|||
BootstrapInfo bootstrapInfo =
|
||||
BootstrapInfo.builder().servers(Collections.singletonList(server)).node(node).build();
|
||||
RefCountedXdsClientObjectPool xdsClientPool =
|
||||
new RefCountedXdsClientObjectPool(bootstrapInfo);
|
||||
new RefCountedXdsClientObjectPool(bootstrapInfo, DUMMY_TARGET);
|
||||
assertThat(xdsClientPool.getXdsClientForTest()).isNull();
|
||||
XdsClient xdsClient = xdsClientPool.getObject();
|
||||
assertThat(xdsClientPool.getXdsClientForTest()).isNotNull();
|
||||
|
@ -103,7 +104,7 @@ public class SharedXdsClientPoolProviderTest {
|
|||
BootstrapInfo bootstrapInfo =
|
||||
BootstrapInfo.builder().servers(Collections.singletonList(server)).node(node).build();
|
||||
RefCountedXdsClientObjectPool xdsClientPool =
|
||||
new RefCountedXdsClientObjectPool(bootstrapInfo);
|
||||
new RefCountedXdsClientObjectPool(bootstrapInfo, DUMMY_TARGET);
|
||||
// getObject once
|
||||
XdsClient xdsClient = xdsClientPool.getObject();
|
||||
assertThat(xdsClient).isNotNull();
|
||||
|
@ -123,7 +124,7 @@ public class SharedXdsClientPoolProviderTest {
|
|||
BootstrapInfo bootstrapInfo =
|
||||
BootstrapInfo.builder().servers(Collections.singletonList(server)).node(node).build();
|
||||
RefCountedXdsClientObjectPool xdsClientPool =
|
||||
new RefCountedXdsClientObjectPool(bootstrapInfo);
|
||||
new RefCountedXdsClientObjectPool(bootstrapInfo, DUMMY_TARGET);
|
||||
XdsClient xdsClient1 = xdsClientPool.getObject();
|
||||
assertThat(xdsClientPool.returnObject(xdsClient1)).isNull();
|
||||
assertThat(xdsClient1.isShutDown()).isTrue();
|
||||
|
|
|
@ -72,12 +72,13 @@ public class XdsClientFederationTest {
|
|||
|
||||
private ObjectPool<XdsClient> xdsClientPool;
|
||||
private XdsClient xdsClient;
|
||||
private static final String DUMMY_TARGET = "dummy";
|
||||
|
||||
@Before
|
||||
public void setUp() throws XdsInitializationException {
|
||||
SharedXdsClientPoolProvider clientPoolProvider = new SharedXdsClientPoolProvider();
|
||||
clientPoolProvider.setBootstrapOverride(defaultBootstrapOverride());
|
||||
xdsClientPool = clientPoolProvider.getOrCreate();
|
||||
xdsClientPool = clientPoolProvider.getOrCreate(DUMMY_TARGET);
|
||||
xdsClient = xdsClientPool.getObject();
|
||||
}
|
||||
|
||||
|
|
|
@ -95,11 +95,15 @@ import io.grpc.xds.client.XdsClient;
|
|||
import io.grpc.xds.client.XdsInitializationException;
|
||||
import io.grpc.xds.client.XdsResourceType;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -166,15 +170,22 @@ public class XdsNameResolverTest {
|
|||
private XdsNameResolver resolver;
|
||||
private TestCall<?, ?> testCall;
|
||||
private boolean originalEnableTimeout;
|
||||
private URI targetUri;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
try {
|
||||
targetUri = new URI(AUTHORITY);
|
||||
} catch (URISyntaxException e) {
|
||||
targetUri = null;
|
||||
}
|
||||
|
||||
originalEnableTimeout = XdsNameResolver.enableTimeout;
|
||||
XdsNameResolver.enableTimeout = true;
|
||||
FilterRegistry filterRegistry = FilterRegistry.newRegistry().register(
|
||||
new FaultFilter(mockRandom, new AtomicLong()),
|
||||
RouterFilter.INSTANCE);
|
||||
resolver = new XdsNameResolver(null, AUTHORITY, null,
|
||||
resolver = new XdsNameResolver(targetUri, null, AUTHORITY, null,
|
||||
serviceConfigParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, filterRegistry, null);
|
||||
}
|
||||
|
@ -199,16 +210,22 @@ public class XdsNameResolverTest {
|
|||
|
||||
@Override
|
||||
@Nullable
|
||||
public ObjectPool<XdsClient> get() {
|
||||
public ObjectPool<XdsClient> get(String target) {
|
||||
throw new UnsupportedOperationException("Should not be called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPool<XdsClient> getOrCreate() throws XdsInitializationException {
|
||||
public ObjectPool<XdsClient> getOrCreate(String target) throws XdsInitializationException {
|
||||
throw new XdsInitializationException("Fail to read bootstrap file");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTargets() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
resolver = new XdsNameResolver(null, AUTHORITY, null,
|
||||
|
||||
resolver = new XdsNameResolver(targetUri, null, AUTHORITY, null,
|
||||
serviceConfigParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver.start(mockListener);
|
||||
|
@ -221,7 +238,7 @@ public class XdsNameResolverTest {
|
|||
|
||||
@Test
|
||||
public void resolving_withTargetAuthorityNotFound() {
|
||||
resolver = new XdsNameResolver(
|
||||
resolver = new XdsNameResolver(targetUri,
|
||||
"notfound.google.com", AUTHORITY, null, serviceConfigParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver.start(mockListener);
|
||||
|
@ -243,7 +260,7 @@ public class XdsNameResolverTest {
|
|||
String serviceAuthority = "[::FFFF:129.144.52.38]:80";
|
||||
expectedLdsResourceName = "[::FFFF:129.144.52.38]:80/id=1";
|
||||
resolver = new XdsNameResolver(
|
||||
null, serviceAuthority, null, serviceConfigParser, syncContext,
|
||||
targetUri, null, serviceAuthority, null, serviceConfigParser, syncContext,
|
||||
scheduler, xdsClientPoolFactory,
|
||||
mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver.start(mockListener);
|
||||
|
@ -264,7 +281,7 @@ public class XdsNameResolverTest {
|
|||
"xdstp://xds.authority.com/envoy.config.listener.v3.Listener/"
|
||||
+ "%5B::FFFF:129.144.52.38%5D:80?id=1";
|
||||
resolver = new XdsNameResolver(
|
||||
null, serviceAuthority, null, serviceConfigParser, syncContext, scheduler,
|
||||
targetUri, null, serviceAuthority, null, serviceConfigParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver.start(mockListener);
|
||||
verify(mockListener, never()).onError(any(Status.class));
|
||||
|
@ -284,7 +301,7 @@ public class XdsNameResolverTest {
|
|||
"xdstp://xds.authority.com/envoy.config.listener.v3.Listener/"
|
||||
+ "path/to/service?id=1";
|
||||
resolver = new XdsNameResolver(
|
||||
null, serviceAuthority, null, serviceConfigParser, syncContext, scheduler,
|
||||
targetUri, null, serviceAuthority, null, serviceConfigParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
|
||||
|
||||
|
@ -311,7 +328,7 @@ public class XdsNameResolverTest {
|
|||
.build();
|
||||
expectedLdsResourceName = "xdstp://xds.authority.com/envoy.config.listener.v3.Listener/"
|
||||
+ "%5B::FFFF:129.144.52.38%5D:80?bar=2&foo=1"; // query param canonified
|
||||
resolver = new XdsNameResolver(
|
||||
resolver = new XdsNameResolver(targetUri,
|
||||
"xds.authority.com", serviceAuthority, null, serviceConfigParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver.start(mockListener);
|
||||
|
@ -343,7 +360,7 @@ public class XdsNameResolverTest {
|
|||
.clientDefaultListenerResourceNameTemplate("test-%s")
|
||||
.node(Node.newBuilder().build())
|
||||
.build();
|
||||
resolver = new XdsNameResolver(null, AUTHORITY, null,
|
||||
resolver = new XdsNameResolver(targetUri, null, AUTHORITY, null,
|
||||
serviceConfigParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
// use different ldsResourceName and service authority. The virtualhost lookup should use
|
||||
|
@ -524,7 +541,7 @@ public class XdsNameResolverTest {
|
|||
Collections.singletonList(route),
|
||||
ImmutableMap.of());
|
||||
|
||||
resolver = new XdsNameResolver(null, AUTHORITY, "random",
|
||||
resolver = new XdsNameResolver(targetUri, null, AUTHORITY, "random",
|
||||
serviceConfigParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver.start(mockListener);
|
||||
|
@ -547,7 +564,7 @@ public class XdsNameResolverTest {
|
|||
Collections.singletonList(route),
|
||||
ImmutableMap.of());
|
||||
|
||||
resolver = new XdsNameResolver(null, AUTHORITY, "random",
|
||||
resolver = new XdsNameResolver(targetUri, null, AUTHORITY, "random",
|
||||
serviceConfigParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver.start(mockListener);
|
||||
|
@ -558,7 +575,7 @@ public class XdsNameResolverTest {
|
|||
|
||||
@Test
|
||||
public void resolving_matchingVirtualHostNotFoundForOverrideAuthority() {
|
||||
resolver = new XdsNameResolver(null, AUTHORITY, AUTHORITY,
|
||||
resolver = new XdsNameResolver(targetUri, null, AUTHORITY, AUTHORITY,
|
||||
serviceConfigParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver.start(mockListener);
|
||||
|
@ -643,8 +660,8 @@ public class XdsNameResolverTest {
|
|||
public void retryPolicyInPerMethodConfigGeneratedByResolverIsValid() {
|
||||
ServiceConfigParser realParser = new ScParser(
|
||||
true, 5, 5, new AutoConfiguredLoadBalancerFactory("pick-first"));
|
||||
resolver = new XdsNameResolver(null, AUTHORITY, null, realParser, syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver = new XdsNameResolver(targetUri, null, AUTHORITY, null, realParser, syncContext,
|
||||
scheduler, xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver.start(mockListener);
|
||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||
RetryPolicy retryPolicy = RetryPolicy.create(
|
||||
|
@ -847,7 +864,7 @@ public class XdsNameResolverTest {
|
|||
resolver.shutdown();
|
||||
reset(mockListener);
|
||||
when(mockRandom.nextLong()).thenReturn(123L);
|
||||
resolver = new XdsNameResolver(null, AUTHORITY, null, serviceConfigParser,
|
||||
resolver = new XdsNameResolver(targetUri, null, AUTHORITY, null, serviceConfigParser,
|
||||
syncContext, scheduler,
|
||||
xdsClientPoolFactory, mockRandom, FilterRegistry.getDefaultRegistry(), null);
|
||||
resolver.start(mockListener);
|
||||
|
@ -1896,17 +1913,20 @@ public class XdsNameResolverTest {
|
|||
}
|
||||
|
||||
private final class FakeXdsClientPoolFactory implements XdsClientPoolFactory {
|
||||
Set<String> targets = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void setBootstrapOverride(Map<String, ?> bootstrap) {}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ObjectPool<XdsClient> get() {
|
||||
public ObjectPool<XdsClient> get(String target) {
|
||||
throw new UnsupportedOperationException("Should not be called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPool<XdsClient> getOrCreate() throws XdsInitializationException {
|
||||
public ObjectPool<XdsClient> getOrCreate(String target) throws XdsInitializationException {
|
||||
targets.add(target);
|
||||
return new ObjectPool<XdsClient>() {
|
||||
@Override
|
||||
public XdsClient getObject() {
|
||||
|
@ -1919,6 +1939,16 @@ public class XdsNameResolverTest {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTargets() {
|
||||
if (targets.isEmpty()) {
|
||||
List<String> targetList = new ArrayList<>();
|
||||
targetList.add(targetUri.toString());
|
||||
return targetList;
|
||||
}
|
||||
return new ArrayList<>(targets);
|
||||
}
|
||||
}
|
||||
|
||||
private class FakeXdsClient extends XdsClient {
|
||||
|
|
|
@ -146,12 +146,12 @@ public class XdsServerTestHelper {
|
|||
|
||||
@Override
|
||||
@Nullable
|
||||
public ObjectPool<XdsClient> get() {
|
||||
public ObjectPool<XdsClient> get(String target) {
|
||||
throw new UnsupportedOperationException("Should not be called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPool<XdsClient> getOrCreate() throws XdsInitializationException {
|
||||
public ObjectPool<XdsClient> getOrCreate(String target) throws XdsInitializationException {
|
||||
return new ObjectPool<XdsClient>() {
|
||||
@Override
|
||||
public XdsClient getObject() {
|
||||
|
@ -165,6 +165,11 @@ public class XdsServerTestHelper {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTargets() {
|
||||
return Collections.singletonList("fake-target");
|
||||
}
|
||||
}
|
||||
|
||||
static final class FakeXdsClient extends XdsClient {
|
||||
|
|
|
@ -135,12 +135,15 @@ final class XdsTestControlPlaneService extends
|
|||
new Object[]{value.getResourceNamesList(), value.getErrorDetail()});
|
||||
return;
|
||||
}
|
||||
|
||||
String resourceType = value.getTypeUrl();
|
||||
if (!value.getResponseNonce().isEmpty()
|
||||
&& !String.valueOf(xdsNonces.get(resourceType)).equals(value.getResponseNonce())) {
|
||||
if (!value.getResponseNonce().isEmpty() && xdsNonces.containsKey(resourceType)
|
||||
&& !String.valueOf(xdsNonces.get(resourceType).get(responseObserver))
|
||||
.equals(value.getResponseNonce())) {
|
||||
logger.log(Level.FINE, "Resource nonce does not match, ignore.");
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> requestedResourceNames = new HashSet<>(value.getResourceNamesList());
|
||||
if (subscribers.get(resourceType).containsKey(responseObserver)
|
||||
&& subscribers.get(resourceType).get(responseObserver)
|
||||
|
@ -149,9 +152,11 @@ final class XdsTestControlPlaneService extends
|
|||
value.getResourceNamesList());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!xdsNonces.get(resourceType).containsKey(responseObserver)) {
|
||||
xdsNonces.get(resourceType).put(responseObserver, new AtomicInteger(0));
|
||||
}
|
||||
|
||||
DiscoveryResponse response = generateResponse(resourceType,
|
||||
String.valueOf(xdsVersions.get(resourceType)),
|
||||
String.valueOf(xdsNonces.get(resourceType).get(responseObserver)),
|
||||
|
|
Loading…
Reference in New Issue