Netty NioEventLoopGroup实例化过程源码分析

4 篇文章 0 订阅

Netty一般的server创建代码

public class NettyServer {
    // 日志
    private Logger log = LoggerFactory.getLogger(getClass());

    // 端口号
    @Value("${netty.port}")
    private int port;

    // 启动服务器方法
    public void run() {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup);
            serverBootstrap.channel(NioServerSocketChannel.class);
            serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024);
            serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
            serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);
            serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
            serverBootstrap.childHandler(new NettyServerInitializer());

            // 绑定端口,开始接收进来的连接
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
            log.info("netty服务启动: [port:" + port + "]");
            // 等待服务器socket关闭
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error("netty服务启动异常-" + e.getMessage());
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}

首先看下new NioEventLoopGroup()到底做了什么,会返回什么:

// 调用自己的构造方法,默认将线程数nThreads赋为0
public NioEventLoopGroup() {
    this(0);
}

public NioEventLoopGroup(int nThreads, Executor executor) {
    // 就是调用NioEventLoopGroup构造函数的一个中间环节,获取provider
    this(nThreads, executor, SelectorProvider.provider());
}

public static SelectorProvider provider() {
    synchronized (lock) {
        if (provider != null)
            return provider;
        return AccessController.doPrivileged(
            new PrivilegedAction<SelectorProvider>() {
                public SelectorProvider run() {
                    // 通过java.nio.channels.spi.SelectorProvider获取spi方式的provider
                    if (loadProviderFromProperty())
                        return provider;
                    // 获取serviceLoader方式的provider
                    if (loadProviderAsService())
                        return provider;
                    // 上述都未找到,则执行默认的,
                    // windows的jdk默认是WindowsSelectorProvider
                    provider = sun.nio.ch.DefaultSelectorProvider.create();
                    return provider;
                }
            });
    }
}

// 返回到构造方法中继续向内部看,最终实际上是调用最终的这个构造方法
public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider, final SelectStrategyFactory selectStrategyFactory) {
    super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}

// 由于NioEventLoopGroup继承了MultithreadEventLoopGroup,所以super方法调用父类的构造方法
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args){
    // 这里注意一下,上面将nThreads赋为0为什么可以初始化成功的原因在这里,如果为0,
    // 取DEFAULT_EVENT_LOOP_THREADS(为CPU核数*2),否则取nThreads
    // DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
    //          "io.netty.eventLoopThreads",       
    //          Runtime.getRuntime().availableProcessors() * 2));
    super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}

// 发现MultithreadEventLoopGroup还是调用了父类MultithreadEventExecutorGroup的构造方法
// 其最终的实现方法为如下方法
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
       EventExecutorChooserFactory chooserFactory, Object... args) {
    if (nThreads <= 0) {
        throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
    }

    if (executor == null) {
        // 实际上就是根据默认线程工厂创建了一个线程池的Executor
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }
    // 根据nThreads数创建一个事件线程执行器组children,即为每个线程都创建一个EventExecutor
    children = new EventExecutor[nThreads];

    for (int i = 0; i < nThreads; i ++) {
        boolean success = false;
        try {
            // 这里实际做的是根据executor和args(包含可接收线程数(默认16)、选择器、拒绝策略)
            // 来实例化每个children
            // 可选的有DefaultEventLoop、EpollEventLoop、NioEventLoop
            // newChild这里执行其实现类NioEventLoop的newChild方法
            children[i] = newChild(executor, args);
            success = true;
        } catch (Exception e) {
            // TODO: Think about if this is a good exception type
            throw new IllegalStateException("failed to create a child event loop", e);
        } finally {
            if (!success) {
                for (int j = 0; j < i; j ++) {
                    // 如果有一个children失败,所有children都执行优雅退出
                    children[j].shutdownGracefully();
                }

                for (int j = 0; j < i; j ++) {
                    EventExecutor e = children[j];
                    try {
                        // 为了让每个未完成的任务执行完成
                        while (!e.isTerminated()) {
                            e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
                        }
                    } catch (InterruptedException interrupted) {
                        // Let the caller handle the interruption.
                        // 如果在等待过程中发生异常,允许响应终端
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
    }
    // 实例化选择器,根据线程数的奇数偶数来选择不通的选择器,主要是因为两个的next方法的实现不同
    chooser = chooserFactory.newChooser(children);
    
    // 实例化终止监听器
    final FutureListener<Object> terminationListener = new FutureListener<Object>() {
        @Override
        public void operationComplete(Future<Object> future) throws Exception {
            if (terminatedChildren.incrementAndGet() == children.length) {
                terminationFuture.setSuccess(null);
            }
        }
    };
    
    // 为每个children都加上terminationListener
    for (EventExecutor e: children) {
        e.terminationFuture().addListener(terminationListener);
    }

    Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
    Collections.addAll(childrenSet, children);
    // 将children存为一个只读的set readonlyChildren
    readonlyChildren = Collections.unmodifiableSet(childrenSet);
}

上述就是new NioEventLoopGroup()的整个流程,下面对上述过程中的几个关键点进行一下细致分析

看下NioEventLoop到底是如何实现的

// 首先上述过程中会调用newChild抽象方法,实际会调用一下方法
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
    return new NioEventLoop(this, executor, (SelectorProvider) args[0],
        ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}

// 可以发现NioEventLoop的构造方法没有public修饰,只能在内部调用
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider, SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
    // super方法请向下看
    super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
    if (selectorProvider == null) {
        throw new NullPointerException("selectorProvider");
    }
    if (strategy == null) {
        throw new NullPointerException("selectStrategy");
    }
    provider = selectorProvider;
    // 请向下看
    selector = openSelector();
    selectStrategy = strategy;
}

// 上面的super方法最后是调用了
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
    boolean addTaskWakesUp, int maxPendingTasks, RejectedExecutionHandler rejectedHandler) {
    super(parent);
    // 为false
    this.addTaskWakesUp = addTaskWakesUp;
    // 最大可接受线程数(task就是一个线程)量取16和maxPendingTasks最大的,默认是16
    this.maxPendingTasks = Math.max(16, maxPendingTasks);
    this.executor = ObjectUtil.checkNotNull(executor, "executor");
    // 初始化task队列
    taskQueue = newTaskQueue(this.maxPendingTasks);
    rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}

// openSelector方法的实现如下
private Selector openSelector() {
    final Selector selector;
    try {
        // 在windows中是调用了new WindowsSelectorImpl(this);
        selector = provider.openSelector();
    } catch (IOException e) {
        throw new ChannelException("failed to open a new selector", e);
    }
    // DISABLE_KEYSET_OPTIMIZATION =
    //      SystemPropertyUtil.getBoolean("io.netty.noKeySetOptimization", false)
    // 是否要进行key优化,即调整key的优先级
    if (DISABLE_KEYSET_OPTIMIZATION) {
        return selector;
    }

    final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();
    // AccessController.doPrivileged可以跳过checkPermission检查,
    // 搜索名为sun.nio.ch.SelectorImpl的实现类
    Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction<Object>() {
        @Override
        public Object run() {
            try {
                return Class.forName(
                    "sun.nio.ch.SelectorImpl",
                    false,
                    PlatformDependent.getSystemClassLoader());
            } catch (ClassNotFoundException e) {
                return e;
            } catch (SecurityException e) {
                return e;
            }
        }
    });
    //判断是不是获取到一个类,是不是selectImpl类,如果是异常trace出来
    if (!(maybeSelectorImplClass instanceof Class) ||
        // ensure the current selector implementation is what we can instrument.
        !((Class<?>) maybeSelectorImplClass).isAssignableFrom(selector.getClass())){
        if (maybeSelectorImplClass instanceof Exception) {
            Exception e = (Exception) maybeSelectorImplClass;
            logger.trace("failed to instrument a special java.util.Set into: {}", selector, e);
        }
        return selector;
    }

    final Class<?> selectorImplClass = (Class<?>) maybeSelectorImplClass;
    // 通过反射将找到的select实现类赋值
    Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
        @Override
        public Object run() {
            try {
                Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
                Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");

                selectedKeysField.setAccessible(true);
                publicSelectedKeysField.setAccessible(true);

                selectedKeysField.set(selector, selectedKeySet);
                publicSelectedKeysField.set(selector, selectedKeySet);
                return null;
            } catch (NoSuchFieldException e) {
                return e;
            } catch (IllegalAccessException e) {
                return e;
            } catch (RuntimeException e) {
                // JDK 9 can throw an inaccessible object exception here; since Netty compiles
                // against JDK 7 and this exception was only added in JDK 9, we have to weakly
                // check the type
                if ("java.lang.reflect.InaccessibleObjectException".equals(e.getClass().getName())) {
                    return e;
                } else {
                    throw e;
                }
            }
        }
    });

    if (maybeException instanceof Exception) {
        selectedKeys = null;
        Exception e = (Exception) maybeException;
        logger.trace("failed to instrument a special java.util.Set into: {}", selector, e);
    } else {
        selectedKeys = selectedKeySet;
        logger.trace("instrumented a special java.util.Set into: {}", selector);
    }

    return selector;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只努力的微服务

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值