Netty 4.1 源代码学习:线程模型

前言

本文以 netty 4.1 自带的示例工程 netty-example 为例,简要介绍 netty 线程模型

EchoServer

echo server 示例工程的代码位于 example/src/main/java/io.netty.example/echo

  • EchoClient

  • EchoClientHandler

  • EchoServer

  • EchoServerHandler

EchoServer 很简单,仅包含一个 main 方法用于初始化 netty server 以及 handler,我们来看看其中和线程模型 相关的一些代码

// EchoServer.java

public static void main(String[] args) throws Exception {
    ...
    // Configure the server
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
          .channel(NioServerSocketChannel.class)
          ...
    } finally {
        ...
    }
}

EventLoop & EventLoopGroup

在 EchoServer 的初始化代码中实例化了两个对象 bossGroup 和 workerGroup,它们有着公共基类 EventLoopGroup,这个 EventLoopGroup 是 netty 线程模型的核心

EventLoopGroup 类名让人联想到 "组合模式",所以肯定有个 EventLoop 类,EventLoopGroup 包含一个或多个 EventLoop

变量名 bossGroup 和 workerGroup 让人联想到 "生产者消费者" 模型,即由 bossGroup 产生消息(事件),然后交给 workerGroup 消费。此外我们注意到 bossGroup 和 workerGroup 使用了不同的构造方法,bossGroup 指定了线程个数 1,workerGroup 则没有,为了发挥硬件性能,一般会根据服务器 CPU 核心个数来设定 "工作者" 线程个数,我们跟踪空构造函数,最终会在父类 MultithreadEventExecutorGroup 中找到当未指定线程个数时(nThreads)netty 会根据 系统属性 io.netty.eventLoopThreads 和 CPU 核心数来确定合适的值

// MultithreadEventLoopGroup.java

public abstract class MultithreadEventLoopGroup extends   
    MultithreadEventExecutorGroup implements EventLoopGroup {


    private static final int DEFAULT_EVENT_LOOP_THREADS;

    static {
        DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
                "io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2));

        if (logger.isDebugEnabled()) {
            logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
        }
    }

    protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
    }
    ...
}

Channel & EventLoop

上文提到 netty 通常使用两个 EventLoopGroup,一个用于生产一个用于消费,那么这两个 EventLoopGroup 是怎么相互通信(耦合)的呢?

总结

  • netty 使用 EventLoopGroup 类封装线程池

  • netty 通常使用两个EventLoopGroup,boss group 和 worker group

  • boss group 用于网络 IO,包括接收客户端连接,读写 socket 等,boss group 通常使用基于 NIO 的事件循环

  • worker group 用于处理 boss group 读取的数据,或者说通常包含应用自身的业务逻辑

相关推荐