Skip to content

开始 ​

官网:Netty: Home

Netty 是高性能、异步事件驱动的网络应用框架,常用于 RPC、网关、长连接、IM、游戏服务器等场景。它封装了 Java NIO 的复杂细节,让开发者更容易编写高性能网络程序。

为什么需要 Netty ​

直接使用 Java NIO 需要处理 Selector、Channel、Buffer、事件循环、半包粘包、线程模型等细节,代码复杂且容易出错。Netty 把这些能力抽象成更清晰的组件。

核心流程 ​

mermaid
flowchart TD
    A["客户端连接"] --> B["BossGroup 接收连接"]
    B --> C["注册到 WorkerGroup"]
    C --> D["ChannelPipeline"]
    D --> E["Decoder 解码"]
    E --> F["业务 Handler"]
    F --> G["Encoder 编码"]
    G --> H["响应客户端"]

这个流程背后的原理是:服务端端口由 BossGroup 监听,新连接建立后变成一个 SocketChannel,再注册到 WorkerGroup 的某个 EventLoop。之后这个连接上的读、写、关闭事件通常都由同一个 EventLoop 处理,再通过 Pipeline 进入不同 Handler。

为什么这样设计:接收连接和处理数据是两类不同工作。接收连接要快,不能被业务逻辑拖慢;处理数据要稳定,要能把协议解析、业务处理、响应编码拆清楚。如果把所有事情都写在一个线程或一个方法里,连接数上来后就会很难定位到底是接入慢、解码慢、业务慢还是写回慢。

核心组件 ​

组件说明
EventLoopGroup线程组,处理连接和 IO 事件
Channel网络连接抽象
ChannelPipelineHandler 责任链
ChannelHandler编解码、业务处理、异常处理
ByteBufNetty 自定义字节缓冲区
Bootstrap客户端或服务端启动辅助类

学习目录 ​

学习建议 ​

先理解 Reactor 线程模型,再看 ChannelPipeline。Netty 的核心是“事件进入 Pipeline 后,被一组 Handler 按顺序处理”。

常见风险 ​

风险后果规避方式
EventLoop 中写耗时代码同一个 EventLoop 上的多个连接一起变慢慢 SQL、远程调用、大计算放到业务线程池
没有定义协议边界TCP 粘包半包导致消息解析错乱使用 LengthFieldBasedFrameDecoder 等拆包器
Handler 顺序随意放解码器、鉴权器、编码器不按预期执行按入站和出站方向设计 Pipeline
忽略连接关闭在线用户表残留无效连接在 channelInactive 中清理资源
忽略 ByteBuf 释放堆外内存泄漏使用 SimpleChannelInboundHandler 或手动 release

代码 Demo:最小 Netty 服务端 ​

java
public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ch.pipeline().addLast(new StringDecoder());
                        ch.pipeline().addLast(new StringEncoder());
                        ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, String msg) {
                                ctx.writeAndFlush("server receive: " + msg);
                            }
                        });
                    }
                });

            ChannelFuture future = bootstrap.bind(8080).sync();
            future.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

这个 Demo 展示了 Netty 服务端的基本结构:BossGroup 接收连接,WorkerGroup 处理 IO,Pipeline 中按顺序放入解码器、编码器和业务 Handler。