【Netty系列】Reactor 模式 1

发布于:2025-05-31 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

一、Reactor 模式的核心思想

二、Netty 中的 Reactor 模式实现

1. 服务端代码示例

2. 处理请求的 Handler

三、运行流程解析(结合 Reactor 模式)

四、关键点说明

五、与传统模型的对比

六、总结


Reactor 模式是 Netty 高性能的核心设计思想之一,它通过 事件驱动异步非阻塞 I/O 实现高并发处理。

下面通过一个服务端处理多请求的例子,详细解释 Reactor 模式在 Netty 中的实现。


一、Reactor 模式的核心思想

Reactor 模式的核心是 分治:将网络连接的建立(Accept)与 I/O 读写(Read/Write)分离到不同的线程处理,避免单线程阻塞。
核心组件:

  1. Reactor:监听事件(如连接请求),并将事件分发给对应的处理器。
  2. Acceptor:处理新连接建立事件。
  3. Handler:处理已建立连接的 I/O 读写事件。

在 Netty 中,Reactor 模式的实现体现为 主从多线程模型

  • 主 Reactor:负责处理连接建立(bossGroup)。
  • 子 Reactor:负责处理 I/O 读写(workerGroup)。

二、Netty 中的 Reactor 模式实现

1. 服务端代码示例

以下是一个 Netty 服务端代码,演示如何接受多个客户端请求:

public class ReactorServerExample {
    public static void main(String[] args) {
        // 主 Reactor(处理连接请求)
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);  // 1 个线程
        // 子 Reactor(处理 I/O 读写)
        EventLoopGroup workerGroup = new NioEventLoopGroup(); // 默认 CPU 核心数 * 2

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(new ServerHandler());
                        }
                    });

            // 绑定端口并启动
            ChannelFuture future = serverBootstrap.bind(8080).sync();
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
2. 处理请求的 Handler
public class ServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        // 处理客户端请求
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("Received: " + buf.toString(CharsetUtil.UTF_8));
        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello Client!", CharsetUtil.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

三、运行流程解析(结合 Reactor 模式)

假设客户端 A 和 B 同时连接服务器:

  1. 主 Reactor(bossGroup)
    • 主 Reactor 的 NioEventLoop 线程负责监听端口(如 8080)。
    • 当客户端 A 和 B 发起连接请求时,主 Reactor 的线程会 顺序处理这些连接请求
    • 每接受一个新连接(accept 事件),主 Reactor 会将新连接的 Channel 注册到子 Reactor(workerGroup)中的一个 EventLoop
  1. 子 Reactor(workerGroup)
    • 子 Reactor 包含多个 EventLoop,每个 EventLoop 绑定一个线程。
    • 客户端 A 和 B 的 Channel 被分配到不同的 EventLoop(例如轮询分配)。
    • 当客户端发送数据时,子 Reactor 的线程负责处理读事件(channelRead),执行 ServerHandler 中的业务逻辑,并返回响应。

四、关键点说明

  1. 非阻塞 I/O
    • 主 Reactor 和子 Reactor 均使用 NIO 的非阻塞模式,单线程可处理多个连接。
    • 例如:一个 EventLoop 线程可以处理多个 Channel 的 I/O 事件。
  1. 线程隔离
    • 主 Reactor 的线程仅处理连接建立,避免 I/O 操作阻塞新连接的接收。
    • 子 Reactor 的线程专注于 I/O 读写,充分利用多核 CPU。
  1. 事件驱动
    • 所有操作(连接、读、写)均由事件触发,避免轮询浪费资源。
    • 例如:当数据到达时,Netty 自动触发 channelRead 事件。

五、与传统模型的对比

模型

线程开销

并发能力

资源利用率

传统 BIO

每个连接一个线程

低(线程数受限)

低(线程阻塞)

Reactor 模式

固定线程池

高(单线程处理多连接)

高(非阻塞)


六、总结

通过 Reactor 模式,Netty 实现了:

  1. 高并发:单线程处理多连接,减少线程切换开销。
  2. 低延迟:非阻塞 I/O 确保事件快速响应。
  3. 易扩展:责任链模式(Pipeline)允许灵活添加业务逻辑。

在示例中,主 Reactor 处理连接,子 Reactor 处理 I/O,多个客户端请求被高效分发到不同线程,最终由 ServerHandler 处理业务逻辑。这就是 Netty 高性能的核心秘密!


网站公告

今日签到

点亮在社区的每一天
去签到