netty: add internal API to fall back to NIO transport (#5611)

This commit is contained in:
Jihun Cho 2019-04-18 13:49:55 -07:00 committed by GitHub
parent 2cdaac2adc
commit dc0171839a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 13 deletions

View File

@ -18,6 +18,8 @@ package io.grpc.netty;
import io.grpc.Internal; import io.grpc.Internal;
import io.grpc.internal.ClientTransportFactory; import io.grpc.internal.ClientTransportFactory;
import io.grpc.internal.SharedResourcePool;
import io.netty.channel.socket.nio.NioSocketChannel;
/** /**
* Internal {@link NettyChannelBuilder} accessor. This is intended for usage internal to the gRPC * Internal {@link NettyChannelBuilder} accessor. This is intended for usage internal to the gRPC
@ -70,6 +72,17 @@ public final class InternalNettyChannelBuilder {
builder.setStatsRecordRealTimeMetrics(value); builder.setStatsRecordRealTimeMetrics(value);
} }
/**
* Sets {@link io.grpc.Channel} and {@link io.netty.channel.EventLoopGroup} to Nio. A major
* benefit over using setters is gRPC will manage the life cycle of {@link
* io.netty.channel.EventLoopGroup}.
*/
public static void useNioTransport(NettyChannelBuilder builder) {
builder.channelType(NioSocketChannel.class);
builder
.eventLoopGroupPool(SharedResourcePool.forResource(Utils.NIO_WORKER_EVENT_LOOP_GROUP));
}
public static ClientTransportFactory buildTransportFactory(NettyChannelBuilder builder) { public static ClientTransportFactory buildTransportFactory(NettyChannelBuilder builder) {
return builder.buildTransportFactory(); return builder.buildTransportFactory();
} }

View File

@ -17,6 +17,8 @@
package io.grpc.netty; package io.grpc.netty;
import io.grpc.Internal; import io.grpc.Internal;
import io.grpc.internal.SharedResourcePool;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/** /**
* Internal {@link InternalNettyServerBuilder} accessor. This is intended for usage internal to * Internal {@link InternalNettyServerBuilder} accessor. This is intended for usage internal to
@ -41,5 +43,19 @@ public final class InternalNettyServerBuilder {
builder.setTracingEnabled(value); builder.setTracingEnabled(value);
} }
/**
* Sets {@link io.grpc.Channel} and {@link io.netty.channel.EventLoopGroup}s to Nio. A major
* benefit over using existing setters is gRPC will manage the life cycle of {@link
* io.netty.channel.EventLoopGroup}s.
*/
public static void useNioTransport(NettyServerBuilder builder) {
builder.channelType(NioServerSocketChannel.class);
builder
.bossEventLoopGroupPool(SharedResourcePool.forResource(Utils.NIO_BOSS_EVENT_LOOP_GROUP));
builder
.workerEventLoopGroupPool(
SharedResourcePool.forResource(Utils.NIO_WORKER_EVENT_LOOP_GROUP));
}
private InternalNettyServerBuilder() {} private InternalNettyServerBuilder() {}
} }

View File

@ -218,10 +218,13 @@ public final class NettyChannelBuilder
*/ */
public NettyChannelBuilder eventLoopGroup(@Nullable EventLoopGroup eventLoopGroup) { public NettyChannelBuilder eventLoopGroup(@Nullable EventLoopGroup eventLoopGroup) {
if (eventLoopGroup != null) { if (eventLoopGroup != null) {
this.eventLoopGroupPool = new FixedObjectPool<>(eventLoopGroup); return eventLoopGroupPool(new FixedObjectPool<>(eventLoopGroup));
} else {
this.eventLoopGroupPool = DEFAULT_EVENT_LOOP_GROUP_POOL;
} }
return eventLoopGroupPool(DEFAULT_EVENT_LOOP_GROUP_POOL);
}
NettyChannelBuilder eventLoopGroupPool(ObjectPool<? extends EventLoopGroup> eventLoopGroupPool) {
this.eventLoopGroupPool = checkNotNull(eventLoopGroupPool, "eventLoopGroupPool");
return this; return this;
} }

View File

@ -81,7 +81,7 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
SharedResourcePool.forResource(Utils.DEFAULT_WORKER_EVENT_LOOP_GROUP); SharedResourcePool.forResource(Utils.DEFAULT_WORKER_EVENT_LOOP_GROUP);
private final List<SocketAddress> listenAddresses = new ArrayList<>(); private final List<SocketAddress> listenAddresses = new ArrayList<>();
private Class<? extends ServerChannel> channelType = Utils.DEFAULT_SERVER_CHANNEL_TYPE; private Class<? extends ServerChannel> channelType = null;
private final Map<ChannelOption<?>, Object> channelOptions = new HashMap<>(); private final Map<ChannelOption<?>, Object> channelOptions = new HashMap<>();
private ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool = private ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool =
DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL; DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL;
@ -193,10 +193,14 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
*/ */
public NettyServerBuilder bossEventLoopGroup(EventLoopGroup group) { public NettyServerBuilder bossEventLoopGroup(EventLoopGroup group) {
if (group != null) { if (group != null) {
this.bossEventLoopGroupPool = new FixedObjectPool<>(group); return bossEventLoopGroupPool(new FixedObjectPool<>(group));
} else {
this.bossEventLoopGroupPool = DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL;
} }
return bossEventLoopGroupPool(DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL);
}
NettyServerBuilder bossEventLoopGroupPool(
ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool) {
this.bossEventLoopGroupPool = checkNotNull(bossEventLoopGroupPool, "bossEventLoopGroupPool");
return this; return this;
} }
@ -225,10 +229,15 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
*/ */
public NettyServerBuilder workerEventLoopGroup(EventLoopGroup group) { public NettyServerBuilder workerEventLoopGroup(EventLoopGroup group) {
if (group != null) { if (group != null) {
this.workerEventLoopGroupPool = new FixedObjectPool<>(group); return workerEventLoopGroupPool(new FixedObjectPool<>(group));
} else {
this.workerEventLoopGroupPool = DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL;
} }
return workerEventLoopGroupPool(DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL);
}
NettyServerBuilder workerEventLoopGroupPool(
ObjectPool<? extends EventLoopGroup> workerEventLoopGroupPool) {
this.workerEventLoopGroupPool =
checkNotNull(workerEventLoopGroupPool, "workerEventLoopGroupPool");
return this; return this;
} }
@ -506,7 +515,7 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
+ "neither should be, otherwise server may not start. Missing values will use Nio " + "neither should be, otherwise server may not start. Missing values will use Nio "
+ "(NioServerSocketChannel, NioEventLoopGroup) for backward compatibility. " + "(NioServerSocketChannel, NioEventLoopGroup) for backward compatibility. "
+ "This will cause an Exception in the future."); + "This will cause an Exception in the future.");
if (channelType == Utils.DEFAULT_SERVER_CHANNEL_TYPE) { if (channelType == null) {
resolvedChannelType = NioServerSocketChannel.class; resolvedChannelType = NioServerSocketChannel.class;
logger.log(Level.FINE, "One or more EventLoopGroup is provided, but Channel type is " logger.log(Level.FINE, "One or more EventLoopGroup is provided, but Channel type is "
+ "missing. Fall back to NioServerSocketChannel."); + "missing. Fall back to NioServerSocketChannel.");
@ -522,6 +531,9 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
+ "BossEventLoopGroup is missing. Fall back to NioEventLoopGroup."); + "BossEventLoopGroup is missing. Fall back to NioEventLoopGroup.");
} }
} }
if (resolvedChannelType == null) {
resolvedChannelType = Utils.DEFAULT_SERVER_CHANNEL_TYPE;
}
List<NettyServer> transportServers = new ArrayList<>(listenAddresses.size()); List<NettyServer> transportServers = new ArrayList<>(listenAddresses.size());
for (SocketAddress listenAddress : listenAddresses) { for (SocketAddress listenAddress : listenAddresses) {
@ -539,10 +551,10 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
@VisibleForTesting @VisibleForTesting
boolean shouldFallBackToNio() { boolean shouldFallBackToNio() {
boolean hasNonDefault = channelType != Utils.DEFAULT_SERVER_CHANNEL_TYPE boolean hasNonDefault = channelType != null
|| bossEventLoopGroupPool != DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL || bossEventLoopGroupPool != DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL
|| workerEventLoopGroupPool != DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL; || workerEventLoopGroupPool != DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL;
boolean hasDefault = channelType == Utils.DEFAULT_SERVER_CHANNEL_TYPE boolean hasDefault = channelType == null
|| bossEventLoopGroupPool == DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL || bossEventLoopGroupPool == DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL
|| workerEventLoopGroupPool == DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL; || workerEventLoopGroupPool == DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL;
return hasNonDefault && hasDefault; return hasNonDefault && hasDefault;

View File

@ -248,4 +248,13 @@ public class NettyChannelBuilderTest {
assertFalse(builder.shouldFallBackToNio()); assertFalse(builder.shouldFallBackToNio());
} }
@Test
public void useNioTransport_shouldNotFallBack() {
NettyChannelBuilder builder = NettyChannelBuilder.forTarget("fakeTarget");
InternalNettyChannelBuilder.useNioTransport(builder);
assertFalse(builder.shouldFallBackToNio());
}
} }

View File

@ -173,4 +173,11 @@ public class NettyServerBuilderTest {
assertFalse(builder.shouldFallBackToNio()); assertFalse(builder.shouldFallBackToNio());
} }
@Test
public void useNioTransport_shouldNotFallBack() {
InternalNettyServerBuilder.useNioTransport(builder);
assertFalse(builder.shouldFallBackToNio());
}
} }