Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 85d1b9f

Browse files
authored
xds: use a standalone Context for xDS control plane RPCs (manual v1.37.x backport) (#8161)
Control plane RPCs are independent of application RPCs, they can stand for completely different lifetime. So the context for making application RPCs should not be propagated to control plane RPCs.
1 parent d6ab21c commit 85d1b9f

File tree

7 files changed

+57
-9
lines changed

7 files changed

+57
-9
lines changed

xds/src/main/java/io/grpc/xds/AbstractXdsClient.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import io.envoyproxy.envoy.service.discovery.v3.AggregatedDiscoveryServiceGrpc;
2929
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryRequest;
3030
import io.envoyproxy.envoy.service.discovery.v3.DiscoveryResponse;
31+
import io.grpc.Context;
3132
import io.grpc.InternalLogId;
3233
import io.grpc.ManagedChannel;
3334
import io.grpc.Status;
@@ -82,6 +83,7 @@ public void uncaughtException(Thread t, Throwable e) {
8283
private final InternalLogId logId;
8384
private final XdsLogger logger;
8485
private final ManagedChannel channel;
86+
private final Context context;
8587
private final boolean useProtocolV3;
8688
private final ScheduledExecutorService timeService;
8789
private final BackoffPolicy.Provider backoffPolicyProvider;
@@ -109,10 +111,11 @@ public void uncaughtException(Thread t, Throwable e) {
109111
@Nullable
110112
private ScheduledHandle rpcRetryTimer;
111113

112-
AbstractXdsClient(ManagedChannel channel, boolean useProtocolV3, Node node,
114+
AbstractXdsClient(ManagedChannel channel, Context context, boolean useProtocolV3, Node node,
113115
ScheduledExecutorService timeService, BackoffPolicy.Provider backoffPolicyProvider,
114116
Supplier<Stopwatch> stopwatchSupplier) {
115117
this.channel = checkNotNull(channel, "channel");
118+
this.context = checkNotNull(context, "context");
116119
this.useProtocolV3 = useProtocolV3;
117120
this.node = checkNotNull(node, "node");
118121
this.timeService = checkNotNull(timeService, "timeService");
@@ -313,7 +316,12 @@ private void startRpcStream() {
313316
} else {
314317
adsStream = new AdsStreamV2();
315318
}
316-
adsStream.start();
319+
Context prevContext = context.attach();
320+
try {
321+
adsStream.start();
322+
} finally {
323+
context.detach(prevContext);
324+
}
317325
logger.log(XdsLogLevel.INFO, "ADS stream started");
318326
stopwatch.reset().start();
319327
}

xds/src/main/java/io/grpc/xds/ClientXdsClient.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds;
5050
import io.envoyproxy.envoy.type.v3.FractionalPercent;
5151
import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType;
52+
import io.grpc.Context;
5253
import io.grpc.EquivalentAddressGroup;
5354
import io.grpc.ManagedChannel;
5455
import io.grpc.Status;
@@ -134,13 +135,14 @@ final class ClientXdsClient extends AbstractXdsClient {
134135
private boolean reportingLoad;
135136

136137
ClientXdsClient(
137-
ManagedChannel channel, boolean useProtocolV3, Node node,
138+
ManagedChannel channel, Context context, boolean useProtocolV3, Node node,
138139
ScheduledExecutorService timeService, BackoffPolicy.Provider backoffPolicyProvider,
139140
Supplier<Stopwatch> stopwatchSupplier, TimeProvider timeProvider) {
140-
super(channel, useProtocolV3, node, timeService, backoffPolicyProvider, stopwatchSupplier);
141+
super(channel, context, useProtocolV3, node, timeService, backoffPolicyProvider,
142+
stopwatchSupplier);
141143
loadStatsManager = new LoadStatsManager2(stopwatchSupplier);
142144
this.timeProvider = timeProvider;
143-
lrsClient = new LoadReportClient(loadStatsManager, channel, useProtocolV3, node,
145+
lrsClient = new LoadReportClient(loadStatsManager, channel, context, useProtocolV3, node,
144146
getSyncContext(), timeService, backoffPolicyProvider, stopwatchSupplier);
145147
}
146148

xds/src/main/java/io/grpc/xds/LoadReportClient.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import io.envoyproxy.envoy.service.load_stats.v3.LoadReportingServiceGrpc.LoadReportingServiceStub;
2929
import io.envoyproxy.envoy.service.load_stats.v3.LoadStatsRequest;
3030
import io.envoyproxy.envoy.service.load_stats.v3.LoadStatsResponse;
31+
import io.grpc.Context;
3132
import io.grpc.InternalLogId;
3233
import io.grpc.ManagedChannel;
3334
import io.grpc.Status;
@@ -55,6 +56,7 @@ final class LoadReportClient {
5556
private final InternalLogId logId;
5657
private final XdsLogger logger;
5758
private final ManagedChannel channel;
59+
private final Context context;
5860
private final boolean useProtocolV3;
5961
private final Node node;
6062
private final SynchronizationContext syncContext;
@@ -74,6 +76,7 @@ final class LoadReportClient {
7476
LoadReportClient(
7577
LoadStatsManager2 loadStatsManager,
7678
ManagedChannel channel,
79+
Context context,
7780
boolean useProtocolV3,
7881
Node node,
7982
SynchronizationContext syncContext,
@@ -82,6 +85,7 @@ final class LoadReportClient {
8285
Supplier<Stopwatch> stopwatchSupplier) {
8386
this.loadStatsManager = checkNotNull(loadStatsManager, "loadStatsManager");
8487
this.channel = checkNotNull(channel, "xdsChannel");
88+
this.context = checkNotNull(context, "context");
8589
this.useProtocolV3 = useProtocolV3;
8690
this.syncContext = checkNotNull(syncContext, "syncContext");
8791
this.timerService = checkNotNull(scheduledExecutorService, "timeService");
@@ -163,7 +167,12 @@ private void startLrsRpc() {
163167
lrsStream = new LrsStreamV2();
164168
}
165169
retryStopwatch.reset().start();
166-
lrsStream.start();
170+
Context prevContext = context.attach();
171+
try {
172+
lrsStream.start();
173+
} finally {
174+
context.detach(prevContext);
175+
}
167176
}
168177

169178
private abstract class LrsStream {

xds/src/main/java/io/grpc/xds/SharedXdsClientPoolProvider.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import com.google.common.annotations.VisibleForTesting;
2222
import io.grpc.ChannelCredentials;
23+
import io.grpc.Context;
2324
import io.grpc.Grpc;
2425
import io.grpc.ManagedChannel;
2526
import io.grpc.internal.ExponentialBackoffPolicy;
@@ -109,6 +110,7 @@ private static class SharedXdsClientPoolProviderHolder {
109110
@ThreadSafe
110111
@VisibleForTesting
111112
static class RefCountedXdsClientObjectPool implements ObjectPool<XdsClient> {
113+
private final Context context = Context.ROOT;
112114
private final String target;
113115
private final ChannelCredentials channelCredentials;
114116
private final Node node;
@@ -140,7 +142,7 @@ public XdsClient getObject() {
140142
.keepAliveTime(5, TimeUnit.MINUTES)
141143
.build();
142144
scheduler = SharedResourceHolder.get(GrpcUtil.TIMER_SERVICE);
143-
xdsClient = new ClientXdsClient(channel, useProtocolV3, node, scheduler,
145+
xdsClient = new ClientXdsClient(channel, context, useProtocolV3, node, scheduler,
144146
new ExponentialBackoffPolicy.Provider(), GrpcUtil.STOPWATCH_SUPPLIER,
145147
TimeProvider.SYSTEM_TIME_PROVIDER);
146148
}

xds/src/main/java/io/grpc/xds/XdsClientWrapperForServerSds.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.common.annotations.VisibleForTesting;
2323
import com.google.common.collect.ImmutableSet;
2424
import com.google.protobuf.UInt32Value;
25+
import io.grpc.Context;
2526
import io.grpc.Grpc;
2627
import io.grpc.Internal;
2728
import io.grpc.ManagedChannel;
@@ -121,6 +122,7 @@ public void createXdsClientAndStart() throws IOException {
121122
XdsClient xdsClientImpl =
122123
new ClientXdsClient(
123124
channel,
125+
Context.ROOT,
124126
serverInfo.isUseProtocolV3(),
125127
node,
126128
timeService,

xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
import static io.grpc.xds.AbstractXdsClient.ResourceType.EDS;
2323
import static io.grpc.xds.AbstractXdsClient.ResourceType.LDS;
2424
import static io.grpc.xds.AbstractXdsClient.ResourceType.RDS;
25+
import static org.mockito.ArgumentMatchers.any;
2526
import static org.mockito.Mockito.mock;
27+
import static org.mockito.Mockito.never;
2628
import static org.mockito.Mockito.times;
2729
import static org.mockito.Mockito.verify;
2830
import static org.mockito.Mockito.verifyNoInteractions;
@@ -40,6 +42,8 @@
4042
import io.envoyproxy.envoy.config.route.v3.FilterConfig;
4143
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.SdsSecretConfig;
4244
import io.grpc.BindableService;
45+
import io.grpc.Context;
46+
import io.grpc.Context.CancellableContext;
4347
import io.grpc.ManagedChannel;
4448
import io.grpc.Status;
4549
import io.grpc.Status.Code;
@@ -258,6 +262,7 @@ public void setUp() throws IOException {
258262
xdsClient =
259263
new ClientXdsClient(
260264
channel,
265+
Context.ROOT,
261266
useProtocolV3(),
262267
EnvoyProtoData.Node.newBuilder().build(),
263268
fakeClock.getScheduledExecutorService(),
@@ -1766,6 +1771,26 @@ public void multipleEdsWatchers() {
17661771
verifySubscribedResourcesMetadataSizes(0, 0, 0, 2);
17671772
}
17681773

1774+
@Test
1775+
public void useIndependentRpcContext() {
1776+
// Simulates making RPCs within the context of an inbound RPC.
1777+
CancellableContext cancellableContext = Context.current().withCancellation();
1778+
Context prevContext = cancellableContext.attach();
1779+
try {
1780+
DiscoveryRpcCall call = startResourceWatcher(LDS, LDS_RESOURCE, ldsResourceWatcher);
1781+
1782+
// The inbound RPC finishes and closes its context. The outbound RPC's control plane RPC
1783+
// should not be impacted.
1784+
cancellableContext.close();
1785+
verify(ldsResourceWatcher, never()).onError(any(Status.class));
1786+
1787+
call.sendResponse(LDS, testListenerRds, VERSION_1, "0000");
1788+
verify(ldsResourceWatcher).onChanged(any(LdsUpdate.class));
1789+
} finally {
1790+
cancellableContext.detach(prevContext);
1791+
}
1792+
}
1793+
17691794
@Test
17701795
public void streamClosedAndRetryWithBackoff() {
17711796
InOrder inOrder = Mockito.inOrder(backoffPolicyProvider, backoffPolicy1, backoffPolicy2);

xds/src/test/java/io/grpc/xds/LoadReportClientTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ public void cancelled(Context context) {
172172
when(backoffPolicy2.nextBackoffNanos())
173173
.thenReturn(TimeUnit.SECONDS.toNanos(2L), TimeUnit.SECONDS.toNanos(20L));
174174
addFakeStatsData();
175-
lrsClient = new LoadReportClient(loadStatsManager, channel, false, NODE, syncContext,
176-
fakeClock.getScheduledExecutorService(), backoffPolicyProvider,
175+
lrsClient = new LoadReportClient(loadStatsManager, channel, Context.ROOT, false, NODE,
176+
syncContext, fakeClock.getScheduledExecutorService(), backoffPolicyProvider,
177177
fakeClock.getStopwatchSupplier());
178178
syncContext.execute(new Runnable() {
179179
@Override

0 commit comments

Comments
 (0)