netty: not using reflection to create NioEventLoopGroup (#5630)

This commit is contained in:
Jihun Cho 2019-04-23 16:45:19 -07:00 committed by GitHub
parent 187fe9e146
commit 67ef8c3466
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 36 additions and 15 deletions

View File

@ -16,6 +16,7 @@
package io.grpc.netty;
import static com.google.common.base.Preconditions.checkState;
import static io.grpc.internal.GrpcUtil.CONTENT_TYPE_KEY;
import static io.grpc.internal.TransportFrameUtil.toHttp2Headers;
import static io.grpc.internal.TransportFrameUtil.toRawSerializedHeaders;
@ -46,6 +47,7 @@ import io.netty.handler.codec.http2.Http2Headers;
import io.netty.util.AsciiString;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.nio.channels.ClosedChannelException;
import java.util.Map;
import java.util.Map.Entry;
@ -73,31 +75,35 @@ class Utils {
public static final AsciiString TE_TRAILERS = AsciiString.of(GrpcUtil.TE_TRAILERS);
public static final AsciiString USER_AGENT = AsciiString.of(GrpcUtil.USER_AGENT_KEY.name());
public static final Resource<EventLoopGroup> NIO_BOSS_EVENT_LOOP_GROUP
= new DefaultEventLoopGroupResource(1, "grpc-nio-boss-ELG", NioEventLoopGroup.class);
= new DefaultEventLoopGroupResource(1, "grpc-nio-boss-ELG", EventLoopGroupType.NIO);
public static final Resource<EventLoopGroup> NIO_WORKER_EVENT_LOOP_GROUP
= new DefaultEventLoopGroupResource(0, "grpc-nio-worker-ELG", NioEventLoopGroup.class);
= new DefaultEventLoopGroupResource(0, "grpc-nio-worker-ELG", EventLoopGroupType.NIO);
public static final Resource<EventLoopGroup> DEFAULT_BOSS_EVENT_LOOP_GROUP;
public static final Resource<EventLoopGroup> DEFAULT_WORKER_EVENT_LOOP_GROUP;
public static final Class<? extends ServerChannel> DEFAULT_SERVER_CHANNEL_TYPE;
public static final Class<? extends Channel> DEFAULT_CLIENT_CHANNEL_TYPE;
@Nullable
private static final Constructor<? extends EventLoopGroup> EPOLL_EVENT_LOOP_GROUP_CONSTRUCTOR;
static {
// Decide default channel types and EventLoopGroup based on Epoll availability
if (isEpollAvailable()) {
DEFAULT_SERVER_CHANNEL_TYPE = epollServerChannelType();
DEFAULT_CLIENT_CHANNEL_TYPE = epollChannelType();
Class<? extends EventLoopGroup> eventLoopGroupType = epollEventLoopGroupType();
EPOLL_EVENT_LOOP_GROUP_CONSTRUCTOR = epollEventLoopGroupConstructor();
DEFAULT_BOSS_EVENT_LOOP_GROUP
= new DefaultEventLoopGroupResource(1, "grpc-default-boss-ELG", eventLoopGroupType);
= new DefaultEventLoopGroupResource(1, "grpc-default-boss-ELG", EventLoopGroupType.EPOLL);
DEFAULT_WORKER_EVENT_LOOP_GROUP
= new DefaultEventLoopGroupResource(0,"grpc-default-worker-ELG", eventLoopGroupType);
= new DefaultEventLoopGroupResource(0,"grpc-default-worker-ELG", EventLoopGroupType.EPOLL);
} else {
logger.log(Level.FINE, "Epoll is not available, using Nio.", getEpollUnavailabilityCause());
DEFAULT_SERVER_CHANNEL_TYPE = NioServerSocketChannel.class;
DEFAULT_CLIENT_CHANNEL_TYPE = NioSocketChannel.class;
DEFAULT_BOSS_EVENT_LOOP_GROUP = NIO_BOSS_EVENT_LOOP_GROUP;
DEFAULT_WORKER_EVENT_LOOP_GROUP = NIO_WORKER_EVENT_LOOP_GROUP;
EPOLL_EVENT_LOOP_GROUP_CONSTRUCTOR = null;
}
}
@ -246,12 +252,15 @@ class Utils {
}
// Must call when epoll is available
private static Class<? extends EventLoopGroup> epollEventLoopGroupType() {
private static Constructor<? extends EventLoopGroup> epollEventLoopGroupConstructor() {
try {
return Class
.forName("io.netty.channel.epoll.EpollEventLoopGroup").asSubclass(EventLoopGroup.class);
.forName("io.netty.channel.epoll.EpollEventLoopGroup").asSubclass(EventLoopGroup.class)
.getConstructor(Integer.TYPE, ThreadFactory.class);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Cannot load EpollEventLoopGroup", e);
} catch (NoSuchMethodException e) {
throw new RuntimeException("EpollEventLoopGroup constructor not found", e);
}
}
@ -268,16 +277,16 @@ class Utils {
}
}
private static EventLoopGroup createEventLoopGroup(
Class<? extends EventLoopGroup> eventLoopGroupType,
private static EventLoopGroup createEpollEventLoopGroup(
int parallelism,
ThreadFactory threadFactory) {
checkState(EPOLL_EVENT_LOOP_GROUP_CONSTRUCTOR != null, "Epoll is not available");
try {
return eventLoopGroupType
.getConstructor(Integer.TYPE, ThreadFactory.class)
return EPOLL_EVENT_LOOP_GROUP_CONSTRUCTOR
.newInstance(parallelism, threadFactory);
} catch (Exception e) {
throw new RuntimeException("Cannot create EventLoopGroup for " + eventLoopGroupType, e);
throw new RuntimeException("Cannot create Epoll EventLoopGroup", e);
}
}
@ -309,10 +318,10 @@ class Utils {
private static final class DefaultEventLoopGroupResource implements Resource<EventLoopGroup> {
private final String name;
private final int numEventLoops;
private final Class<? extends EventLoopGroup> eventLoopGroupType;
private final EventLoopGroupType eventLoopGroupType;
DefaultEventLoopGroupResource(
int numEventLoops, String name, Class<? extends EventLoopGroup> eventLoopGroupType) {
int numEventLoops, String name, EventLoopGroupType eventLoopGroupType) {
this.name = name;
this.numEventLoops = numEventLoops;
this.eventLoopGroupType = eventLoopGroupType;
@ -322,7 +331,14 @@ class Utils {
public EventLoopGroup create() {
// Use Netty's DefaultThreadFactory in order to get the benefit of FastThreadLocal.
ThreadFactory threadFactory = new DefaultThreadFactory(name, /* daemon= */ true);
return createEventLoopGroup(eventLoopGroupType, numEventLoops, threadFactory);
switch (eventLoopGroupType) {
case NIO:
return new NioEventLoopGroup(numEventLoops, threadFactory);
case EPOLL:
return createEpollEventLoopGroup(numEventLoops, threadFactory);
default:
throw new AssertionError("Unknown/Unsupported EventLoopGroupType: " + eventLoopGroupType);
}
}
@Override
@ -375,6 +391,11 @@ class Utils {
return b.build();
}
private enum EventLoopGroupType {
NIO,
EPOLL
}
private Utils() {
// Prevents instantiation
}