1 /* 2 * Copyright 2014 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.netty; 18 19 import static com.google.common.base.Preconditions.checkArgument; 20 import static com.google.common.base.Preconditions.checkNotNull; 21 import static com.google.common.base.Preconditions.checkState; 22 import static io.grpc.internal.GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE; 23 import static io.grpc.internal.GrpcUtil.DEFAULT_SERVER_KEEPALIVE_TIMEOUT_NANOS; 24 import static io.grpc.internal.GrpcUtil.DEFAULT_SERVER_KEEPALIVE_TIME_NANOS; 25 import static io.grpc.internal.GrpcUtil.SERVER_KEEPALIVE_TIME_NANOS_DISABLED; 26 27 import com.google.common.annotations.VisibleForTesting; 28 import com.google.errorprone.annotations.CanIgnoreReturnValue; 29 import com.google.errorprone.annotations.CheckReturnValue; 30 import com.google.errorprone.annotations.InlineMe; 31 import io.grpc.Attributes; 32 import io.grpc.ExperimentalApi; 33 import io.grpc.Internal; 34 import io.grpc.ServerBuilder; 35 import io.grpc.ServerCredentials; 36 import io.grpc.ServerStreamTracer; 37 import io.grpc.internal.AbstractServerImplBuilder; 38 import io.grpc.internal.FixedObjectPool; 39 import io.grpc.internal.GrpcUtil; 40 import io.grpc.internal.InternalServer; 41 import io.grpc.internal.KeepAliveManager; 42 import io.grpc.internal.ObjectPool; 43 import io.grpc.internal.ServerImplBuilder; 44 import io.grpc.internal.ServerImplBuilder.ClientTransportServersBuilder; 45 import io.grpc.internal.SharedResourcePool; 46 import io.grpc.internal.TransportTracer; 47 import io.netty.channel.ChannelFactory; 48 import io.netty.channel.ChannelOption; 49 import io.netty.channel.EventLoopGroup; 50 import io.netty.channel.ReflectiveChannelFactory; 51 import io.netty.channel.ServerChannel; 52 import io.netty.channel.socket.nio.NioServerSocketChannel; 53 import io.netty.handler.ssl.SslContext; 54 import java.io.File; 55 import java.io.InputStream; 56 import java.net.InetSocketAddress; 57 import java.net.SocketAddress; 58 import java.util.ArrayList; 59 import java.util.HashMap; 60 import java.util.List; 61 import java.util.Map; 62 import java.util.concurrent.TimeUnit; 63 import javax.net.ssl.SSLException; 64 65 /** 66 * A builder to help simplify the construction of a Netty-based GRPC server. 67 */ 68 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1784") 69 @CheckReturnValue 70 public final class NettyServerBuilder extends AbstractServerImplBuilder<NettyServerBuilder> { 71 72 // 1MiB 73 public static final int DEFAULT_FLOW_CONTROL_WINDOW = 1024 * 1024; 74 75 static final long MAX_CONNECTION_IDLE_NANOS_DISABLED = Long.MAX_VALUE; 76 static final long MAX_CONNECTION_AGE_NANOS_DISABLED = Long.MAX_VALUE; 77 static final long MAX_CONNECTION_AGE_GRACE_NANOS_INFINITE = Long.MAX_VALUE; 78 79 private static final long MIN_KEEPALIVE_TIME_NANO = TimeUnit.MILLISECONDS.toNanos(1L); 80 private static final long MIN_KEEPALIVE_TIMEOUT_NANO = TimeUnit.MICROSECONDS.toNanos(499L); 81 private static final long MIN_MAX_CONNECTION_IDLE_NANO = TimeUnit.SECONDS.toNanos(1L); 82 private static final long MIN_MAX_CONNECTION_AGE_NANO = TimeUnit.SECONDS.toNanos(1L); 83 private static final long AS_LARGE_AS_INFINITE = TimeUnit.DAYS.toNanos(1000L); 84 private static final ObjectPool<? extends EventLoopGroup> DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL = 85 SharedResourcePool.forResource(Utils.DEFAULT_BOSS_EVENT_LOOP_GROUP); 86 private static final ObjectPool<? extends EventLoopGroup> DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL = 87 SharedResourcePool.forResource(Utils.DEFAULT_WORKER_EVENT_LOOP_GROUP); 88 89 private final ServerImplBuilder serverImplBuilder; 90 private final List<SocketAddress> listenAddresses = new ArrayList<>(); 91 92 private TransportTracer.Factory transportTracerFactory = TransportTracer.getDefaultFactory(); 93 private ChannelFactory<? extends ServerChannel> channelFactory = 94 Utils.DEFAULT_SERVER_CHANNEL_FACTORY; 95 private final Map<ChannelOption<?>, Object> channelOptions = new HashMap<>(); 96 private final Map<ChannelOption<?>, Object> childChannelOptions = new HashMap<>(); 97 private ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool = 98 DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL; 99 private ObjectPool<? extends EventLoopGroup> workerEventLoopGroupPool = 100 DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL; 101 private boolean forceHeapBuffer; 102 private ProtocolNegotiator.ServerFactory protocolNegotiatorFactory; 103 private final boolean freezeProtocolNegotiatorFactory; 104 private int maxConcurrentCallsPerConnection = Integer.MAX_VALUE; 105 private boolean autoFlowControl = true; 106 private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW; 107 private int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE; 108 private int maxHeaderListSize = GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE; 109 private long keepAliveTimeInNanos = DEFAULT_SERVER_KEEPALIVE_TIME_NANOS; 110 private long keepAliveTimeoutInNanos = DEFAULT_SERVER_KEEPALIVE_TIMEOUT_NANOS; 111 private long maxConnectionIdleInNanos = MAX_CONNECTION_IDLE_NANOS_DISABLED; 112 private long maxConnectionAgeInNanos = MAX_CONNECTION_AGE_NANOS_DISABLED; 113 private long maxConnectionAgeGraceInNanos = MAX_CONNECTION_AGE_GRACE_NANOS_INFINITE; 114 private boolean permitKeepAliveWithoutCalls; 115 private long permitKeepAliveTimeInNanos = TimeUnit.MINUTES.toNanos(5); 116 private Attributes eagAttributes = Attributes.EMPTY; 117 118 /** 119 * Creates a server builder that will bind to the given port. 120 * 121 * @param port the port on which the server is to be bound. 122 * @return the server builder. 123 */ forPort(int port)124 public static NettyServerBuilder forPort(int port) { 125 return forAddress(new InetSocketAddress(port)); 126 } 127 128 /** 129 * Creates a server builder that will bind to the given port. 130 * 131 * @param port the port on which the server is to be bound. 132 * @return the server builder. 133 */ forPort(int port, ServerCredentials creds)134 public static NettyServerBuilder forPort(int port, ServerCredentials creds) { 135 return forAddress(new InetSocketAddress(port), creds); 136 } 137 138 /** 139 * Creates a server builder configured with the given {@link SocketAddress}. 140 * 141 * @param address the socket address on which the server is to be bound. 142 * @return the server builder 143 */ forAddress(SocketAddress address)144 public static NettyServerBuilder forAddress(SocketAddress address) { 145 return new NettyServerBuilder(address); 146 } 147 148 /** 149 * Creates a server builder configured with the given {@link SocketAddress}. 150 * 151 * @param address the socket address on which the server is to be bound. 152 * @return the server builder 153 */ forAddress(SocketAddress address, ServerCredentials creds)154 public static NettyServerBuilder forAddress(SocketAddress address, ServerCredentials creds) { 155 ProtocolNegotiators.FromServerCredentialsResult result = ProtocolNegotiators.from(creds); 156 if (result.error != null) { 157 throw new IllegalArgumentException(result.error); 158 } 159 return new NettyServerBuilder(address, result.negotiator); 160 } 161 162 private final class NettyClientTransportServersBuilder implements ClientTransportServersBuilder { 163 @Override buildClientTransportServers( List<? extends ServerStreamTracer.Factory> streamTracerFactories)164 public InternalServer buildClientTransportServers( 165 List<? extends ServerStreamTracer.Factory> streamTracerFactories) { 166 return buildTransportServers(streamTracerFactories); 167 } 168 } 169 NettyServerBuilder(SocketAddress address)170 private NettyServerBuilder(SocketAddress address) { 171 serverImplBuilder = new ServerImplBuilder(new NettyClientTransportServersBuilder()); 172 this.listenAddresses.add(address); 173 this.protocolNegotiatorFactory = ProtocolNegotiators.serverPlaintextFactory(); 174 this.freezeProtocolNegotiatorFactory = false; 175 } 176 NettyServerBuilder(SocketAddress address, ProtocolNegotiator.ServerFactory negotiatorFactory)177 NettyServerBuilder(SocketAddress address, ProtocolNegotiator.ServerFactory negotiatorFactory) { 178 serverImplBuilder = new ServerImplBuilder(new NettyClientTransportServersBuilder()); 179 this.listenAddresses.add(address); 180 this.protocolNegotiatorFactory = checkNotNull(negotiatorFactory, "negotiatorFactory"); 181 this.freezeProtocolNegotiatorFactory = true; 182 } 183 184 @Internal 185 @Override delegate()186 protected ServerBuilder<?> delegate() { 187 return serverImplBuilder; 188 } 189 190 /** 191 * Adds an additional address for this server to listen on. Callers must ensure that all socket 192 * addresses are compatible with the Netty channel type, and that they don't conflict with each 193 * other. 194 */ 195 @CanIgnoreReturnValue addListenAddress(SocketAddress listenAddress)196 public NettyServerBuilder addListenAddress(SocketAddress listenAddress) { 197 this.listenAddresses.add(checkNotNull(listenAddress, "listenAddress")); 198 return this; 199 } 200 201 /** 202 * Specifies the channel type to use, by default we use {@code EpollServerSocketChannel} if 203 * available, otherwise using {@link NioServerSocketChannel}. 204 * 205 * <p>You either use this or {@link #channelFactory(io.netty.channel.ChannelFactory)} if your 206 * {@link ServerChannel} implementation has no no-args constructor. 207 * 208 * <p>It's an optional parameter. If the user has not provided an Channel type or ChannelFactory 209 * when the channel is built, the builder will use the default one which is static. 210 * 211 * <p>You must also provide corresponding {@link EventLoopGroup} using {@link 212 * #workerEventLoopGroup(EventLoopGroup)} and {@link #bossEventLoopGroup(EventLoopGroup)}. For 213 * example, {@link NioServerSocketChannel} must use {@link 214 * io.netty.channel.nio.NioEventLoopGroup}, otherwise your server won't start. 215 */ 216 @CanIgnoreReturnValue channelType(Class<? extends ServerChannel> channelType)217 public NettyServerBuilder channelType(Class<? extends ServerChannel> channelType) { 218 checkNotNull(channelType, "channelType"); 219 return channelFactory(new ReflectiveChannelFactory<>(channelType)); 220 } 221 222 /** 223 * Specifies the {@link ChannelFactory} to create {@link ServerChannel} instances. This method is 224 * usually only used if the specific {@code ServerChannel} requires complex logic which requires 225 * additional information to create the {@code ServerChannel}. Otherwise, recommend to use {@link 226 * #channelType(Class)}. 227 * 228 * <p>It's an optional parameter. If the user has not provided an Channel type or ChannelFactory 229 * when the channel is built, the builder will use the default one which is static. 230 * 231 * <p>You must also provide corresponding {@link EventLoopGroup} using {@link 232 * #workerEventLoopGroup(EventLoopGroup)} and {@link #bossEventLoopGroup(EventLoopGroup)}. For 233 * example, if the factory creates {@link NioServerSocketChannel} you must use {@link 234 * io.netty.channel.nio.NioEventLoopGroup}, otherwise your server won't start. 235 */ 236 @CanIgnoreReturnValue channelFactory(ChannelFactory<? extends ServerChannel> channelFactory)237 public NettyServerBuilder channelFactory(ChannelFactory<? extends ServerChannel> channelFactory) { 238 this.channelFactory = checkNotNull(channelFactory, "channelFactory"); 239 return this; 240 } 241 242 /** 243 * Specifies a channel option. As the underlying channel as well as network implementation may 244 * ignore this value applications should consider it a hint. 245 * 246 * @since 1.30.0 247 */ 248 @CanIgnoreReturnValue withOption(ChannelOption<T> option, T value)249 public <T> NettyServerBuilder withOption(ChannelOption<T> option, T value) { 250 this.channelOptions.put(option, value); 251 return this; 252 } 253 254 /** 255 * Specifies a child channel option. As the underlying channel as well as network implementation 256 * may ignore this value applications should consider it a hint. 257 * 258 * @since 1.9.0 259 */ 260 @CanIgnoreReturnValue withChildOption(ChannelOption<T> option, T value)261 public <T> NettyServerBuilder withChildOption(ChannelOption<T> option, T value) { 262 this.childChannelOptions.put(option, value); 263 return this; 264 } 265 266 /** 267 * Provides the boss EventGroupLoop to the server. 268 * 269 * <p>It's an optional parameter. If the user has not provided one when the server is built, the 270 * builder will use the default one which is static. 271 * 272 * <p>You must also provide corresponding {@link io.netty.channel.Channel} type using {@link 273 * #channelType(Class)} and {@link #workerEventLoopGroup(EventLoopGroup)}. For example, {@link 274 * NioServerSocketChannel} must use {@link io.netty.channel.nio.NioEventLoopGroup} for both boss 275 * and worker {@link EventLoopGroup}, otherwise your server won't start. 276 * 277 * <p>The server won't take ownership of the given EventLoopGroup. It's caller's responsibility 278 * to shut it down when it's desired. 279 * 280 * <p>Grpc uses non-daemon {@link Thread}s by default and thus a {@link io.grpc.Server} will 281 * continue to run even after the main thread has terminated. However, users have to be cautious 282 * when providing their own {@link EventLoopGroup}s. 283 * For example, Netty's {@link EventLoopGroup}s use daemon threads by default 284 * and thus an application with only daemon threads running besides the main thread will exit as 285 * soon as the main thread completes. 286 * A simple solution to this problem is to call {@link io.grpc.Server#awaitTermination()} to 287 * keep the main thread alive until the server has terminated. 288 */ 289 @CanIgnoreReturnValue bossEventLoopGroup(EventLoopGroup group)290 public NettyServerBuilder bossEventLoopGroup(EventLoopGroup group) { 291 if (group != null) { 292 return bossEventLoopGroupPool(new FixedObjectPool<>(group)); 293 } 294 return bossEventLoopGroupPool(DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL); 295 } 296 297 @CanIgnoreReturnValue bossEventLoopGroupPool( ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool)298 NettyServerBuilder bossEventLoopGroupPool( 299 ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool) { 300 this.bossEventLoopGroupPool = checkNotNull(bossEventLoopGroupPool, "bossEventLoopGroupPool"); 301 return this; 302 } 303 304 /** 305 * Provides the worker EventGroupLoop to the server. 306 * 307 * <p>It's an optional parameter. If the user has not provided one when the server is built, the 308 * builder will create one. 309 * 310 * <p>You must also provide corresponding {@link io.netty.channel.Channel} type using {@link 311 * #channelType(Class)} and {@link #bossEventLoopGroup(EventLoopGroup)}. For example, {@link 312 * NioServerSocketChannel} must use {@link io.netty.channel.nio.NioEventLoopGroup} for both boss 313 * and worker {@link EventLoopGroup}, otherwise your server won't start. 314 * 315 * <p>The server won't take ownership of the given EventLoopGroup. It's caller's responsibility 316 * to shut it down when it's desired. 317 * 318 * <p>Grpc uses non-daemon {@link Thread}s by default and thus a {@link io.grpc.Server} will 319 * continue to run even after the main thread has terminated. However, users have to be cautious 320 * when providing their own {@link EventLoopGroup}s. 321 * For example, Netty's {@link EventLoopGroup}s use daemon threads by default 322 * and thus an application with only daemon threads running besides the main thread will exit as 323 * soon as the main thread completes. 324 * A simple solution to this problem is to call {@link io.grpc.Server#awaitTermination()} to 325 * keep the main thread alive until the server has terminated. 326 */ 327 @CanIgnoreReturnValue workerEventLoopGroup(EventLoopGroup group)328 public NettyServerBuilder workerEventLoopGroup(EventLoopGroup group) { 329 if (group != null) { 330 return workerEventLoopGroupPool(new FixedObjectPool<>(group)); 331 } 332 return workerEventLoopGroupPool(DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL); 333 } 334 335 @CanIgnoreReturnValue workerEventLoopGroupPool( ObjectPool<? extends EventLoopGroup> workerEventLoopGroupPool)336 NettyServerBuilder workerEventLoopGroupPool( 337 ObjectPool<? extends EventLoopGroup> workerEventLoopGroupPool) { 338 this.workerEventLoopGroupPool = 339 checkNotNull(workerEventLoopGroupPool, "workerEventLoopGroupPool"); 340 return this; 341 } 342 343 /** 344 * Force using heap buffer when custom allocator is enabled. 345 */ setForceHeapBuffer(boolean value)346 void setForceHeapBuffer(boolean value) { 347 forceHeapBuffer = value; 348 } 349 350 /** 351 * Sets the TLS context to use for encryption. Providing a context enables encryption. It must 352 * have been configured with {@link GrpcSslContexts}, but options could have been overridden. 353 */ 354 @CanIgnoreReturnValue sslContext(SslContext sslContext)355 public NettyServerBuilder sslContext(SslContext sslContext) { 356 checkState(!freezeProtocolNegotiatorFactory, 357 "Cannot change security when using ServerCredentials"); 358 if (sslContext != null) { 359 checkArgument(sslContext.isServer(), 360 "Client SSL context can not be used for server"); 361 GrpcSslContexts.ensureAlpnAndH2Enabled(sslContext.applicationProtocolNegotiator()); 362 protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext); 363 } else { 364 protocolNegotiatorFactory = ProtocolNegotiators.serverPlaintextFactory(); 365 } 366 return this; 367 } 368 369 /** 370 * Sets the {@link ProtocolNegotiator} to be used. Overrides the value specified in {@link 371 * #sslContext(SslContext)}. 372 */ 373 @CanIgnoreReturnValue 374 @Internal protocolNegotiator(ProtocolNegotiator protocolNegotiator)375 public final NettyServerBuilder protocolNegotiator(ProtocolNegotiator protocolNegotiator) { 376 checkState(!freezeProtocolNegotiatorFactory, 377 "Cannot change security when using ServerCredentials"); 378 this.protocolNegotiatorFactory = ProtocolNegotiators.fixedServerFactory(protocolNegotiator); 379 return this; 380 } 381 setTracingEnabled(boolean value)382 void setTracingEnabled(boolean value) { 383 this.serverImplBuilder.setTracingEnabled(value); 384 } 385 setStatsEnabled(boolean value)386 void setStatsEnabled(boolean value) { 387 this.serverImplBuilder.setStatsEnabled(value); 388 } 389 setStatsRecordStartedRpcs(boolean value)390 void setStatsRecordStartedRpcs(boolean value) { 391 this.serverImplBuilder.setStatsRecordStartedRpcs(value); 392 } 393 setStatsRecordRealTimeMetrics(boolean value)394 void setStatsRecordRealTimeMetrics(boolean value) { 395 this.serverImplBuilder.setStatsRecordRealTimeMetrics(value); 396 } 397 398 /** 399 * The maximum number of concurrent calls permitted for each incoming connection. Defaults to no 400 * limit. 401 */ 402 @CanIgnoreReturnValue maxConcurrentCallsPerConnection(int maxCalls)403 public NettyServerBuilder maxConcurrentCallsPerConnection(int maxCalls) { 404 checkArgument(maxCalls > 0, "max must be positive: %s", maxCalls); 405 this.maxConcurrentCallsPerConnection = maxCalls; 406 return this; 407 } 408 409 /** 410 * Sets the initial flow control window in bytes. Setting initial flow control window enables auto 411 * flow control tuning using bandwidth-delay product algorithm. To disable auto flow control 412 * tuning, use {@link #flowControlWindow(int)}. By default, auto flow control is enabled with 413 * initial flow control window size of {@link #DEFAULT_FLOW_CONTROL_WINDOW}. 414 */ 415 @CanIgnoreReturnValue initialFlowControlWindow(int initialFlowControlWindow)416 public NettyServerBuilder initialFlowControlWindow(int initialFlowControlWindow) { 417 checkArgument(initialFlowControlWindow > 0, "initialFlowControlWindow must be positive"); 418 this.flowControlWindow = initialFlowControlWindow; 419 this.autoFlowControl = true; 420 return this; 421 } 422 423 /** 424 * Sets the flow control window in bytes. Setting flowControlWindow disables auto flow control 425 * tuning; use {@link #initialFlowControlWindow(int)} to enable auto flow control tuning. If not 426 * called, the default value is {@link #DEFAULT_FLOW_CONTROL_WINDOW}) with auto flow control 427 * tuning. 428 */ 429 @CanIgnoreReturnValue flowControlWindow(int flowControlWindow)430 public NettyServerBuilder flowControlWindow(int flowControlWindow) { 431 checkArgument(flowControlWindow > 0, "flowControlWindow must be positive: %s", 432 flowControlWindow); 433 this.flowControlWindow = flowControlWindow; 434 this.autoFlowControl = false; 435 return this; 436 } 437 438 /** 439 * Sets the maximum message size allowed to be received on the server. If not called, 440 * defaults to 4 MiB. The default provides protection to services who haven't considered the 441 * possibility of receiving large messages while trying to be large enough to not be hit in normal 442 * usage. 443 * 444 * @deprecated Call {@link #maxInboundMessageSize} instead. This method will be removed in a 445 * future release. 446 */ 447 @CanIgnoreReturnValue 448 @Deprecated 449 @InlineMe(replacement = "this.maxInboundMessageSize(maxMessageSize)") maxMessageSize(int maxMessageSize)450 public NettyServerBuilder maxMessageSize(int maxMessageSize) { 451 return maxInboundMessageSize(maxMessageSize); 452 } 453 454 /** {@inheritDoc} */ 455 @CanIgnoreReturnValue 456 @Override maxInboundMessageSize(int bytes)457 public NettyServerBuilder maxInboundMessageSize(int bytes) { 458 checkArgument(bytes >= 0, "bytes must be non-negative: %s", bytes); 459 this.maxMessageSize = bytes; 460 return this; 461 } 462 463 /** 464 * Sets the maximum size of header list allowed to be received. This is cumulative size of the 465 * headers with some overhead, as defined for 466 * <a href="http://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2"> 467 * HTTP/2's SETTINGS_MAX_HEADER_LIST_SIZE</a>. The default is 8 KiB. 468 * 469 * @deprecated Use {@link #maxInboundMetadataSize} instead 470 */ 471 @CanIgnoreReturnValue 472 @Deprecated 473 @InlineMe(replacement = "this.maxInboundMetadataSize(maxHeaderListSize)") maxHeaderListSize(int maxHeaderListSize)474 public NettyServerBuilder maxHeaderListSize(int maxHeaderListSize) { 475 return maxInboundMetadataSize(maxHeaderListSize); 476 } 477 478 /** 479 * Sets the maximum size of metadata allowed to be received. This is cumulative size of the 480 * entries with some overhead, as defined for 481 * <a href="http://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2"> 482 * HTTP/2's SETTINGS_MAX_HEADER_LIST_SIZE</a>. The default is 8 KiB. 483 * 484 * @param bytes the maximum size of received metadata 485 * @return this 486 * @throws IllegalArgumentException if bytes is non-positive 487 * @since 1.17.0 488 */ 489 @CanIgnoreReturnValue 490 @Override maxInboundMetadataSize(int bytes)491 public NettyServerBuilder maxInboundMetadataSize(int bytes) { 492 checkArgument(bytes > 0, "maxInboundMetadataSize must be positive: %s", bytes); 493 this.maxHeaderListSize = bytes; 494 return this; 495 } 496 497 /** 498 * Sets a custom keepalive time, the delay time for sending next keepalive ping. An unreasonably 499 * small value might be increased, and {@code Long.MAX_VALUE} nano seconds or an unreasonably 500 * large value will disable keepalive. 501 * 502 * @since 1.3.0 503 */ 504 @CanIgnoreReturnValue 505 @Override keepAliveTime(long keepAliveTime, TimeUnit timeUnit)506 public NettyServerBuilder keepAliveTime(long keepAliveTime, TimeUnit timeUnit) { 507 checkArgument(keepAliveTime > 0L, "keepalive time must be positive:%s", keepAliveTime); 508 keepAliveTimeInNanos = timeUnit.toNanos(keepAliveTime); 509 keepAliveTimeInNanos = KeepAliveManager.clampKeepAliveTimeInNanos(keepAliveTimeInNanos); 510 if (keepAliveTimeInNanos >= AS_LARGE_AS_INFINITE) { 511 // Bump keepalive time to infinite. This disables keep alive. 512 keepAliveTimeInNanos = SERVER_KEEPALIVE_TIME_NANOS_DISABLED; 513 } 514 if (keepAliveTimeInNanos < MIN_KEEPALIVE_TIME_NANO) { 515 // Bump keepalive time. 516 keepAliveTimeInNanos = MIN_KEEPALIVE_TIME_NANO; 517 } 518 return this; 519 } 520 521 /** 522 * Sets a custom keepalive timeout, the timeout for keepalive ping requests. An unreasonably small 523 * value might be increased. 524 * 525 * @since 1.3.0 526 */ 527 @CanIgnoreReturnValue 528 @Override keepAliveTimeout(long keepAliveTimeout, TimeUnit timeUnit)529 public NettyServerBuilder keepAliveTimeout(long keepAliveTimeout, TimeUnit timeUnit) { 530 checkArgument(keepAliveTimeout > 0L, "keepalive timeout must be positive: %s", 531 keepAliveTimeout); 532 keepAliveTimeoutInNanos = timeUnit.toNanos(keepAliveTimeout); 533 keepAliveTimeoutInNanos = 534 KeepAliveManager.clampKeepAliveTimeoutInNanos(keepAliveTimeoutInNanos); 535 if (keepAliveTimeoutInNanos < MIN_KEEPALIVE_TIMEOUT_NANO) { 536 // Bump keepalive timeout. 537 keepAliveTimeoutInNanos = MIN_KEEPALIVE_TIMEOUT_NANO; 538 } 539 return this; 540 } 541 542 /** 543 * Sets a custom max connection idle time, connection being idle for longer than which will be 544 * gracefully terminated. Idleness duration is defined since the most recent time the number of 545 * outstanding RPCs became zero or the connection establishment. An unreasonably small value might 546 * be increased. {@code Long.MAX_VALUE} nano seconds or an unreasonably large value will disable 547 * max connection idle. 548 * 549 * @since 1.4.0 550 */ 551 @CanIgnoreReturnValue 552 @Override maxConnectionIdle(long maxConnectionIdle, TimeUnit timeUnit)553 public NettyServerBuilder maxConnectionIdle(long maxConnectionIdle, TimeUnit timeUnit) { 554 checkArgument(maxConnectionIdle > 0L, "max connection idle must be positive: %s", 555 maxConnectionIdle); 556 maxConnectionIdleInNanos = timeUnit.toNanos(maxConnectionIdle); 557 if (maxConnectionIdleInNanos >= AS_LARGE_AS_INFINITE) { 558 maxConnectionIdleInNanos = MAX_CONNECTION_IDLE_NANOS_DISABLED; 559 } 560 if (maxConnectionIdleInNanos < MIN_MAX_CONNECTION_IDLE_NANO) { 561 maxConnectionIdleInNanos = MIN_MAX_CONNECTION_IDLE_NANO; 562 } 563 return this; 564 } 565 566 /** 567 * Sets a custom max connection age, connection lasting longer than which will be gracefully 568 * terminated. An unreasonably small value might be increased. A random jitter of +/-10% will be 569 * added to it. {@code Long.MAX_VALUE} nano seconds or an unreasonably large value will disable 570 * max connection age. 571 * 572 * @since 1.3.0 573 */ 574 @CanIgnoreReturnValue 575 @Override maxConnectionAge(long maxConnectionAge, TimeUnit timeUnit)576 public NettyServerBuilder maxConnectionAge(long maxConnectionAge, TimeUnit timeUnit) { 577 checkArgument(maxConnectionAge > 0L, "max connection age must be positive: %s", 578 maxConnectionAge); 579 maxConnectionAgeInNanos = timeUnit.toNanos(maxConnectionAge); 580 if (maxConnectionAgeInNanos >= AS_LARGE_AS_INFINITE) { 581 maxConnectionAgeInNanos = MAX_CONNECTION_AGE_NANOS_DISABLED; 582 } 583 if (maxConnectionAgeInNanos < MIN_MAX_CONNECTION_AGE_NANO) { 584 maxConnectionAgeInNanos = MIN_MAX_CONNECTION_AGE_NANO; 585 } 586 return this; 587 } 588 589 /** 590 * Sets a custom grace time for the graceful connection termination. Once the max connection age 591 * is reached, RPCs have the grace time to complete. RPCs that do not complete in time will be 592 * cancelled, allowing the connection to terminate. {@code Long.MAX_VALUE} nano seconds or an 593 * unreasonably large value are considered infinite. 594 * 595 * @see #maxConnectionAge(long, TimeUnit) 596 * @since 1.3.0 597 */ 598 @CanIgnoreReturnValue 599 @Override maxConnectionAgeGrace(long maxConnectionAgeGrace, TimeUnit timeUnit)600 public NettyServerBuilder maxConnectionAgeGrace(long maxConnectionAgeGrace, TimeUnit timeUnit) { 601 checkArgument(maxConnectionAgeGrace >= 0L, "max connection age grace must be non-negative: %s", 602 maxConnectionAgeGrace); 603 maxConnectionAgeGraceInNanos = timeUnit.toNanos(maxConnectionAgeGrace); 604 if (maxConnectionAgeGraceInNanos >= AS_LARGE_AS_INFINITE) { 605 maxConnectionAgeGraceInNanos = MAX_CONNECTION_AGE_GRACE_NANOS_INFINITE; 606 } 607 return this; 608 } 609 610 /** 611 * Specify the most aggressive keep-alive time clients are permitted to configure. The server will 612 * try to detect clients exceeding this rate and when detected will forcefully close the 613 * connection. The default is 5 minutes. 614 * 615 * <p>Even though a default is defined that allows some keep-alives, clients must not use 616 * keep-alive without approval from the service owner. Otherwise, they may experience failures in 617 * the future if the service becomes more restrictive. When unthrottled, keep-alives can cause a 618 * significant amount of traffic and CPU usage, so clients and servers should be conservative in 619 * what they use and accept. 620 * 621 * @see #permitKeepAliveWithoutCalls(boolean) 622 * @since 1.3.0 623 */ 624 @CanIgnoreReturnValue 625 @Override permitKeepAliveTime(long keepAliveTime, TimeUnit timeUnit)626 public NettyServerBuilder permitKeepAliveTime(long keepAliveTime, TimeUnit timeUnit) { 627 checkArgument(keepAliveTime >= 0, "permit keepalive time must be non-negative: %s", 628 keepAliveTime); 629 permitKeepAliveTimeInNanos = timeUnit.toNanos(keepAliveTime); 630 return this; 631 } 632 633 /** 634 * Sets whether to allow clients to send keep-alive HTTP/2 PINGs even if there are no outstanding 635 * RPCs on the connection. Defaults to {@code false}. 636 * 637 * @see #permitKeepAliveTime(long, TimeUnit) 638 * @since 1.3.0 639 */ 640 @CanIgnoreReturnValue 641 @Override permitKeepAliveWithoutCalls(boolean permit)642 public NettyServerBuilder permitKeepAliveWithoutCalls(boolean permit) { 643 permitKeepAliveWithoutCalls = permit; 644 return this; 645 } 646 647 /** Sets the EAG attributes available to protocol negotiators. Not for general use. */ eagAttributes(Attributes eagAttributes)648 void eagAttributes(Attributes eagAttributes) { 649 this.eagAttributes = checkNotNull(eagAttributes, "eagAttributes"); 650 } 651 buildTransportServers( List<? extends ServerStreamTracer.Factory> streamTracerFactories)652 NettyServer buildTransportServers( 653 List<? extends ServerStreamTracer.Factory> streamTracerFactories) { 654 assertEventLoopsAndChannelType(); 655 656 ProtocolNegotiator negotiator = protocolNegotiatorFactory.newNegotiator( 657 this.serverImplBuilder.getExecutorPool()); 658 659 return new NettyServer( 660 listenAddresses, channelFactory, channelOptions, childChannelOptions, 661 bossEventLoopGroupPool, workerEventLoopGroupPool, forceHeapBuffer, negotiator, 662 streamTracerFactories, transportTracerFactory, maxConcurrentCallsPerConnection, 663 autoFlowControl, flowControlWindow, maxMessageSize, maxHeaderListSize, 664 keepAliveTimeInNanos, keepAliveTimeoutInNanos, 665 maxConnectionIdleInNanos, maxConnectionAgeInNanos, 666 maxConnectionAgeGraceInNanos, permitKeepAliveWithoutCalls, permitKeepAliveTimeInNanos, 667 eagAttributes, this.serverImplBuilder.getChannelz()); 668 } 669 670 @VisibleForTesting assertEventLoopsAndChannelType()671 void assertEventLoopsAndChannelType() { 672 boolean allProvided = channelFactory != Utils.DEFAULT_SERVER_CHANNEL_FACTORY 673 && bossEventLoopGroupPool != DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL 674 && workerEventLoopGroupPool != DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL; 675 boolean nonProvided = channelFactory == Utils.DEFAULT_SERVER_CHANNEL_FACTORY 676 && bossEventLoopGroupPool == DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL 677 && workerEventLoopGroupPool == DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL; 678 checkState( 679 allProvided || nonProvided, 680 "All of BossEventLoopGroup, WorkerEventLoopGroup and ChannelType should be provided or " 681 + "neither should be"); 682 } 683 684 @CanIgnoreReturnValue setTransportTracerFactory(TransportTracer.Factory transportTracerFactory)685 NettyServerBuilder setTransportTracerFactory(TransportTracer.Factory transportTracerFactory) { 686 this.transportTracerFactory = transportTracerFactory; 687 return this; 688 } 689 690 @CanIgnoreReturnValue 691 @Override useTransportSecurity(File certChain, File privateKey)692 public NettyServerBuilder useTransportSecurity(File certChain, File privateKey) { 693 checkState(!freezeProtocolNegotiatorFactory, 694 "Cannot change security when using ServerCredentials"); 695 SslContext sslContext; 696 try { 697 sslContext = GrpcSslContexts.forServer(certChain, privateKey).build(); 698 } catch (SSLException e) { 699 // This should likely be some other, easier to catch exception. 700 throw new RuntimeException(e); 701 } 702 protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext); 703 return this; 704 } 705 706 @CanIgnoreReturnValue 707 @Override useTransportSecurity(InputStream certChain, InputStream privateKey)708 public NettyServerBuilder useTransportSecurity(InputStream certChain, InputStream privateKey) { 709 checkState(!freezeProtocolNegotiatorFactory, 710 "Cannot change security when using ServerCredentials"); 711 SslContext sslContext; 712 try { 713 sslContext = GrpcSslContexts.forServer(certChain, privateKey).build(); 714 } catch (SSLException e) { 715 // This should likely be some other, easier to catch exception. 716 throw new RuntimeException(e); 717 } 718 protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext); 719 return this; 720 } 721 } 722