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。