Java NIO 根据操作系统不同,对 Selector 有不同的实现。比如:
- macosx 是 KQueueSelectorProvider
 - windows 有 WindowsSelectorProvider
 - Linux 有 EPollSelectorProvider (Linux kernels >= 2.6,是 epoll 模式)或 PollSelectorProvider(selector模式)
 
自4.0.16起,Netty 为 Linux 通过 JNI 的方式提供了 native socket transport。
Oracle jdk 会自动选择合适的 Selector,Oracle JDK 在 Linux 已经默认使用 epoll 方式, 为什么netty还要提供一个基于 epoll 的实现呢?
stackoverflow 也解释过,具体可参阅官方 native-transports,Tomcat Native
If you are running on linux you can use EpollEventLoopGroup and so get better performance, less GC and have more advanced features that are only available on linux.
- Netty 的 epoll transport 使用 epoll edge-triggered 而 java 的 nio 使用 level-triggered
 - Netty的 epoll transport 暴露了更多的nio没有的配置参数, 如 TCP_CORK, SO_REUSEADDR等。
 - C 代码,更少 GC,更少 synchronized
 
总之,linux 上使用 EpollEventLoopGroup 会有较少的 gc 有更高级的特性,性能更好~!
那该如何使用 native socket transport(epoll)呢?
其实只需将相应的类替换即可
很多优秀的源码中对此都进行了兼容性处理,比如 rocketmq
//源于org.apache.rocketmq.remoting.nettypublic class NettyRemotingServer extends NettyRemotingAbstract implements RemotingServer {public NettyRemotingServer(final NettyServerConfig nettyServerConfig,final ChannelEventListener channelEventListener) {super(nettyServerConfig.getServerOnewaySemaphoreValue(), nettyServerConfig.getServerAsyncSemaphoreValue());this.serverBootstrap = new ServerBootstrap();this.nettyServerConfig = nettyServerConfig;this.channelEventListener = channelEventListener;int publicThreadNums = nettyServerConfig.getServerCallbackExecutorThreads();if (publicThreadNums <= 0) {publicThreadNums = 4;}this.publicExecutor = Executors.newFixedThreadPool(publicThreadNums, new ThreadFactory() {private AtomicInteger threadIndex = new AtomicInteger(0);@Overridepublic Thread newThread(Runnable r) {return new Thread(r, "NettyServerPublicExecutor_" + this.threadIndex.incrementAndGet());}});if (useEpoll()) {this.eventLoopGroupBoss = new EpollEventLoopGroup(1, new ThreadFactory() {private AtomicInteger threadIndex = new AtomicInteger(0);@Overridepublic Thread newThread(Runnable r) {return new Thread(r, String.format("NettyEPOLLBoss_%d", this.threadIndex.incrementAndGet()));}});this.eventLoopGroupSelector = new EpollEventLoopGroup(nettyServerConfig.getServerSelectorThreads(), new ThreadFactory() {private AtomicInteger threadIndex = new AtomicInteger(0);private int threadTotal = nettyServerConfig.getServerSelectorThreads();@Overridepublic Thread newThread(Runnable r) {return new Thread(r, String.format("NettyServerEPOLLSelector_%d_%d", threadTotal, this.threadIndex.incrementAndGet()));}});} else {this.eventLoopGroupBoss = new NioEventLoopGroup(1, new ThreadFactory() {private AtomicInteger threadIndex = new AtomicInteger(0);@Overridepublic Thread newThread(Runnable r) {return new Thread(r, String.format("NettyNIOBoss_%d", this.threadIndex.incrementAndGet()));}});this.eventLoopGroupSelector = new NioEventLoopGroup(nettyServerConfig.getServerSelectorThreads(), new ThreadFactory() {private AtomicInteger threadIndex = new AtomicInteger(0);private int threadTotal = nettyServerConfig.getServerSelectorThreads();@Overridepublic Thread newThread(Runnable r) {return new Thread(r, String.format("NettyServerNIOSelector_%d_%d", threadTotal, this.threadIndex.incrementAndGet()));}});}loadSslContext();}private boolean useEpoll() {return RemotingUtil.isLinuxPlatform()&& nettyServerConfig.isUseEpollNativeSelector()&& Epoll.isAvailable();}}
[
](https://blog.csdn.net/alex_xfboy/article/details/89643638)
