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 读取的数据,或者说通常包含应用自身的业务逻辑