前言
本文以 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 读取的数据,或者说通常包含应用自身的业务逻辑
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。