Prompts-MCP 686 skills · ai / design / design-pattern / framework / fundamentals / habit / lang / tech-selection /mcp/sse
framework framework/netty/reactor-thread-model.md high

netty-reactor-thread-model

Netty 主从 Reactor 线程模型 — boss EventLoopGroup 只 accept,worker 处理 IO 读写,耗时业务必须丢业务线程池不能阻塞 EventLoop。Use when 配 EventLoopGroup / 设线程数 / 业务耗时阻塞 IO 线程时。

reactor 线程模型eventloopgroupboss workerio 线程阻塞业务线程池
paths
  • *.java

Netty · 主从 Reactor 线程模型

本条只管「线程组怎么配、业务放哪」。Handler 链怎么组见 pipeline-handler.md;心跳见 heartbeat-and-bytebuf.md

规则

约定
boss 组 只负责 accept 新连接,线程数 1 即可(单端口监听)
worker 组 负责已建连接的 IO 读写,默认线程数 = CPU 核数 × 2
铁律 EventLoop 线程绝不能执行耗时操作(DB/RPC/锁/大计算),否则阻塞该线程上所有连接
耗时业务 丢自定义业务线程池(DefaultEventExecutorGroup 或普通线程池),IO 线程立即返回
单线程归属 一个 Channel 全生命周期固定绑一个 EventLoop,Handler 内无需加锁(无并发)
优雅关闭 shutdownGracefully() 关两个组,不要 System.exit 硬关

正例:主从 Reactor 启动 + 业务丢线程池

EventLoopGroup boss = new NioEventLoopGroup(1);          // 只 accept
EventLoopGroup worker = new NioEventLoopGroup();         // 默认 核数×2,处理 IO
EventExecutorGroup biz = new DefaultEventExecutorGroup(16); // 业务线程池
try {
    ServerBootstrap b = new ServerBootstrap();
    b.group(boss, worker).channel(NioServerSocketChannel.class)
     .childHandler(new ChannelInitializer<SocketChannel>() {
        protected void initChannel(SocketChannel ch) {
            ch.pipeline()
              .addLast(new MyDecoder())
              // 耗时业务 Handler 绑到业务线程池,不占 worker
              .addLast(biz, new BizHandler());
        }
     });
    b.bind(8080).sync().channel().closeFuture().sync();
} finally {
    boss.shutdownGracefully();
    worker.shutdownGracefully();
}

反例

// ❌ 在 worker(IO) 线程里直接做耗时操作:阻塞该 EventLoop 上所有连接
protected void channelRead0(ChannelHandlerContext ctx, Msg msg) {
    Order o = orderMapper.selectById(msg.getId());  // 同步 DB,阻塞 IO 线程
    Thread.sleep(2000);                               // 更致命
    ctx.writeAndFlush(o);
}

// ❌ boss 组配几十个线程:accept 用不上,纯浪费
EventLoopGroup boss = new NioEventLoopGroup(32);

自检

  • [ ] boss 组线程数为 1(单端口),worker 用默认(核数×2)?
  • [ ] EventLoop 线程内没有任何 DB/RPC/sleep/重计算等阻塞操作?
  • [ ] 耗时业务 Handler 绑到了独立业务线程池(addLast 传 EventExecutorGroup)?
  • [ ] 关闭用 shutdownGracefully() 关两个组?

相关