zoukankan      html  css  js  c++  java
  • netty笔记-:EpollEventLoopGroup:Caused by: java.lang.ExceptionInInitializerError:Caused by: java.lang.IllegalStateException: Only supported on Linux

    今天在翻看netty的源码的时候发现netty对EventLoopGroup的实现有不止常用的NIOEventLoopGroup ,一共有以下几种。

    • EpollEventLoopGroup
    • NioEventLoopGroup
    • KQueueEventLoopGroup

      其中NioEventLoopGroup则是我们比较常用的,这个使用了java NIO中的SelectorProvider.provider()来选择系统默认的selectorProvider(即多路复用IO的支持)。

    public NioEventLoopGroup(ThreadFactory threadFactory) {
            this(0, threadFactory, SelectorProvider.provider());
        }

    而JDK则会根据自己的版本来返回默认的。

        public static SelectorProvider provider() {
            synchronized (lock) {
                if (provider != null)
                    return provider;
                return AccessController.doPrivileged(
                    new PrivilegedAction<SelectorProvider>() {
                        public SelectorProvider run() {
                                if (loadProviderFromProperty())
                                    return provider;
                                if (loadProviderAsService())
                                    return provider;
                                provider = sun.nio.ch.DefaultSelectorProvider.create();
                                return provider;
                            }
                        });
            }
        }

      如果我们没有在参数中指定,那么provider = sun.nio.ch.DefaultSelectorProvider.create();这句代码则会找到当前jdk版本默认的selectorProvider。 不同的系统对应的默认selectorProvider不一样。
    oracle jdk也会根据发行的不同操作系统的版本来提供不同的selectorProvider实现 例如windows的
    则是WindowsSelectorProvider (注意本文是以oracle jdk为例,open jdk这儿的实现是不一样的)

    public class DefaultSelectorProvider {
        private DefaultSelectorProvider() {
        }
    
        public static SelectorProvider create() {
            return new WindowsSelectorProvider();
        }
    }

      而BSD/MAC OS则是KQueue->KQueueSelectorProvider ,linux则是Epoll->EPollSelectorProvider(注意linux 2.5.44以后才提供,之前均为select/poll) 。而java NIO会根据jvm的版本来选择合适的selectorProvider,使用这个是确保不会出现系统

    切换的问题,即java跨平台的特性还是得到保证的。那netty为何还要多此一举的为EPollSelectorProvider和KQueueSelectorProvider单独提供对应的EventLoopGroup即EpollEventLoopGroup和KQueueEventLoopGroup呢。要知道手动指定会有操作系统不匹配的风险,例如如下代码

    public class Server {
    
        public static void main(String[] args) throws InterruptedException {
    
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            ChannelFuture channelFuture = serverBootstrap.group(new EpollEventLoopGroup(1) , new EpollEventLoopGroup(10))
                    .channel(EpollServerSocketChannel.class)
                    .handler(new LoggingHandler())
                    .childHandler(new InitialierHandler())
                    .bind(8080)
                    .sync();
            channelFuture.channel().closeFuture().sync();
        }
    }

      如果这段代码在windows或者mac os上运行则会报本文标题上的错  (将其中EpollEnventLoopGroup换为NIOEventLoopGroup,EpollServerSocketChannel 换为NIOsERVERSocketChannel则可以平台通用)

    Exception in thread "main" java.lang.UnsatisfiedLinkError: failed to load the required native library
        at io.netty.channel.epoll.Epoll.ensureAvailability(Epoll.java:80)
        at io.netty.channel.epoll.EpollEventLoop.<clinit>(EpollEventLoop.java:51)
        at io.netty.channel.epoll.EpollEventLoopGroup.newChild(EpollEventLoopGroup.java:150)
        at io.netty.channel.epoll.EpollEventLoopGroup.newChild(EpollEventLoopGroup.java:35)
        at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:84)
        at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:58)
        at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:47)
        at io.netty.channel.MultithreadEventLoopGroup.<init>(MultithreadEventLoopGroup.java:59)
        at io.netty.channel.epoll.EpollEventLoopGroup.<init>(EpollEventLoopGroup.java:112)
        at io.netty.channel.epoll.EpollEventLoopGroup.<init>(EpollEventLoopGroup.java:99)
        at io.netty.channel.epoll.EpollEventLoopGroup.<init>(EpollEventLoopGroup.java:76)
        at io.netty.channel.epoll.EpollEventLoopGroup.<init>(EpollEventLoopGroup.java:52)
        at netty.Server.main(Server.java:22)
    Caused by: java.lang.ExceptionInInitializerError
        at io.netty.channel.epoll.Epoll.<clinit>(Epoll.java:39)
        ... 12 more
    Caused by: java.lang.IllegalStateException: Only supported on Linux
        at io.netty.channel.epoll.Native.loadNativeLibrary(Native.java:225)
        at io.netty.channel.epoll.Native.<clinit>(Native.java:58)
        ... 13 more

      俗话说,有风险,肯定就有收益。netty单独提供的epoll/KQueue实现肯定是有性能上的优化的。这儿可以引用一下官方文档,地址:https://netty.io/wiki/native-transports.html

      其中大概的解释了下原因。

       即相比于java NIO,提供了更多的特定平台的功能,产生更少的垃圾,总体上提高了性能。java JDK因为要保证跨平台所以在功能上必须做出妥协

      

        所以我们在构建项目的时候可以根据项目指定环境的不同来指定不同的EnventLoopGroup提升性能。例如开发环境 windows可以使用java的NIO ,mac可以使用netty定制的KqueueSelector.

      生产环境一般为linux则可以使用netty定制的EpollSelector来提高负载性能

  • 相关阅读:
    文件较验及Google Gson的使用
    SQLite数据库操作
    错误收集
    【记录】Linux安装JDK详细步骤
    【原创】RPM安装软件时解决依赖性问题(自动解决依赖型)
    【原创】rman备份出现ORA-19625
    【原创】rman 全库备份脚本
    【原创】TimeSten安装与配置
    【原创】查询占CPU高的oracle进程
    【参考】查找Oracle最高的几个等待事件以及锁的信息
  • 原文地址:https://www.cnblogs.com/hetutu-5238/p/12186582.html
Copyright © 2011-2022 走看看