Skip to content
This repository was archived by the owner on Sep 26, 2023. It is now read-only.

Commit 0cee27d

Browse files
authored
Allow InstantiatingGrpcChannelProvider to specify maxHeaderListSize (#581)
Allow InstantiatingGrpcChannelProvider to specify maxHeaderListSize. When the value is specified, use NettyChannelBuilder to create the channel.
1 parent fffc665 commit 0cee27d

File tree

4 files changed

+69
-8
lines changed

4 files changed

+69
-8
lines changed

build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ subprojects {
112112
grpcStub: "io.grpc:grpc-stub:${grpcVersion}",
113113
grpcAuth: "io.grpc:grpc-auth:${grpcVersion}",
114114
grpcProtobuf: "io.grpc:grpc-protobuf:${grpcVersion}",
115-
grpcNetty: "io.grpc:grpc-netty-shaded:${grpcVersion}",
115+
grpcNetty: "io.grpc:grpc-netty:${grpcVersion}",
116+
grpcNettyShaded: "io.grpc:grpc-netty-shaded:${grpcVersion}",
116117
gson: "com.google.code.gson:gson:2.7",
117118
guava: 'com.google.guava:guava:20.0',
118119
jsr305: 'com.google.code.findbugs:jsr305:3.0.2',

gax-grpc/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ dependencies {
1212
libraries.auth,
1313
libraries.authCredentials,
1414
libraries.commonProtos,
15-
libraries.apiCommon
15+
libraries.apiCommon,
16+
libraries.grpcNettyShaded
1617

1718
compileOnly libraries.autovalue
19+
compileOnly libraries.grpcNetty
1820

1921
testCompile project(':gax').sourceSets.test.output,
2022
libraries.junit,

gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP
6868
private final String endpoint;
6969
@Nullable private final GrpcInterceptorProvider interceptorProvider;
7070
@Nullable private final Integer maxInboundMessageSize;
71+
@Nullable private final Integer maxInboundMetadataSize;
7172
@Nullable private final Duration keepAliveTime;
7273
@Nullable private final Duration keepAliveTimeout;
7374
@Nullable private final Boolean keepAliveWithoutCalls;
@@ -80,6 +81,7 @@ private InstantiatingGrpcChannelProvider(Builder builder) {
8081
this.endpoint = builder.endpoint;
8182
this.interceptorProvider = builder.interceptorProvider;
8283
this.maxInboundMessageSize = builder.maxInboundMessageSize;
84+
this.maxInboundMetadataSize = builder.maxInboundMetadataSize;
8385
this.keepAliveTime = builder.keepAliveTime;
8486
this.keepAliveTimeout = builder.keepAliveTimeout;
8587
this.keepAliveWithoutCalls = builder.keepAliveWithoutCalls;
@@ -181,12 +183,38 @@ private ManagedChannel createSingleChannel() throws IOException {
181183
int port = Integer.parseInt(endpoint.substring(colon + 1));
182184
String serviceAddress = endpoint.substring(0, colon);
183185

184-
ManagedChannelBuilder builder =
185-
ManagedChannelBuilder.forAddress(serviceAddress, port)
186-
.intercept(headerInterceptor)
187-
.intercept(metadataHandlerInterceptor)
188-
.userAgent(headerInterceptor.getUserAgentHeader())
189-
.executor(executor);
186+
// TODO(hzyi): Use NettyChannelBuilder when maxInboundMetadataSize is specified to unblock Spanner.
187+
// Change to ManagedChannelBuilder when https://github.com/grpc/grpc-java/issues/4050 is
188+
// resolved.
189+
ManagedChannelBuilder builder;
190+
if (maxInboundMetadataSize != null) {
191+
try {
192+
Class.forName("io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder");
193+
builder =
194+
io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder.forAddress(serviceAddress, port)
195+
.maxHeaderListSize(maxInboundMetadataSize);
196+
} catch (ClassNotFoundException e) {
197+
try {
198+
Class.forName("io.grpc.netty.NettyChannelBuilder");
199+
builder =
200+
io.grpc.netty.NettyChannelBuilder.forAddress(serviceAddress, port)
201+
.maxHeaderListSize(maxInboundMetadataSize);
202+
} catch (ClassNotFoundException ex) {
203+
throw new RuntimeException(
204+
"Unable to create the channel because neither"
205+
+ " \"io.grpc.netty.NettyChannelBuilder\" nor"
206+
+ " \"io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder\" is found.");
207+
}
208+
}
209+
} else {
210+
builder = ManagedChannelBuilder.forAddress(serviceAddress, port);
211+
}
212+
213+
builder
214+
.intercept(headerInterceptor)
215+
.intercept(metadataHandlerInterceptor)
216+
.userAgent(headerInterceptor.getUserAgentHeader())
217+
.executor(executor);
190218
if (maxInboundMessageSize != null) {
191219
builder.maxInboundMessageSize(maxInboundMessageSize);
192220
}
@@ -226,6 +254,12 @@ public Boolean getKeepAliveWithoutCalls() {
226254
return keepAliveWithoutCalls;
227255
}
228256

257+
/** The maximum metadata size allowed to be received on the channel. */
258+
@BetaApi("The surface for maximum metadata size is not stable yet and may change in the future.")
259+
public Integer getMaxInboundMetadataSize() {
260+
return maxInboundMetadataSize;
261+
}
262+
229263
@Override
230264
public boolean shouldAutoClose() {
231265
return true;
@@ -246,6 +280,7 @@ public static final class Builder {
246280
private String endpoint;
247281
@Nullable private GrpcInterceptorProvider interceptorProvider;
248282
@Nullable private Integer maxInboundMessageSize;
283+
@Nullable private Integer maxInboundMetadataSize;
249284
@Nullable private Duration keepAliveTime;
250285
@Nullable private Duration keepAliveTimeout;
251286
@Nullable private Boolean keepAliveWithoutCalls;
@@ -262,6 +297,7 @@ private Builder(InstantiatingGrpcChannelProvider provider) {
262297
this.endpoint = provider.endpoint;
263298
this.interceptorProvider = provider.interceptorProvider;
264299
this.maxInboundMessageSize = provider.maxInboundMessageSize;
300+
this.maxInboundMetadataSize = provider.maxInboundMetadataSize;
265301
this.keepAliveTime = provider.keepAliveTime;
266302
this.keepAliveTimeout = provider.keepAliveTimeout;
267303
this.keepAliveWithoutCalls = provider.keepAliveWithoutCalls;
@@ -333,6 +369,21 @@ public Integer getMaxInboundMessageSize() {
333369
return maxInboundMessageSize;
334370
}
335371

372+
/** The maximum metadata size allowed to be received on the channel. */
373+
@BetaApi(
374+
"The surface for maximum metadata size is not stable yet and may change in the future.")
375+
public Builder setMaxInboundMetadataSize(Integer max) {
376+
this.maxInboundMetadataSize = max;
377+
return this;
378+
}
379+
380+
/** The maximum metadata size allowed to be received on the channel. */
381+
@BetaApi(
382+
"The surface for maximum metadata size is not stable yet and may change in the future.")
383+
public Integer getMaxInboundMetadataSize() {
384+
return maxInboundMetadataSize;
385+
}
386+
336387
/** The time without read activity before sending a keepalive ping. */
337388
public Builder setKeepAliveTime(Duration duration) {
338389
this.keepAliveTime = duration;

gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ public void testKeepAlive() {
9090
assertEquals(provider.getKeepAliveWithoutCalls(), keepaliveWithoutCalls);
9191
}
9292

93+
@Test
94+
public void testMaxInboundMetadataSize() {
95+
InstantiatingGrpcChannelProvider provider =
96+
InstantiatingGrpcChannelProvider.newBuilder().setMaxInboundMetadataSize(4096).build();
97+
assertThat(provider.getMaxInboundMetadataSize()).isEqualTo(4096);
98+
}
99+
93100
@Test
94101
public void testCpuPoolSize() {
95102
// happy path

0 commit comments

Comments
 (0)