一、Netty是什么?
Netty 是一个基于Java NIO的异步事件驱动网络应用框架,用于快速开发高性能、高可靠性的网络服务器和客户端程序。由JBOSS提供并成为业界最流行的网络框架之一,支撑着包括Dubbo、RocketMQ、Elasticsearch等众多知名中间件的底层通信。
核心优势:
-
✅ 高性能:零拷贝技术、内存池、Reactor线程模型
-
✅ 易用性:简化NIO的复杂API,提供开箱即用的编解码器
-
✅ 可扩展性:模块化设计,支持自定义协议
-
✅ 稳定性:经历大规模商业项目验证(如日均亿级请求场景)
二、Netty核心组件全景图
(示意图:Netty核心架构分层)
1. 核心三剑客
① Channel(通道)
-
对应NIO的
SocketChannel
,代表一个网络连接 -
重要方法:
channel.write() // 写数据 channel.read() // 读数据 channel.close() // 关闭连接
② EventLoop(事件循环)
-
一个
EventLoop
处理多个Channel
的所有I/O操作 -
线程模型:每个EventLoop绑定一个独立线程
EventLoopGroup group = new NioEventLoopGroup(4); // 4个线程
③ ChannelHandler(处理器)
-
处理I/O事件的核心组件
-
典型实现:
public class MyHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { // 处理收到的数据 } }
2. 核心辅助类
① ByteBuf(缓冲区)
-
Netty的数据容器,相比NIO的ByteBuffer:
-
支持动态扩容
-
读写索引分离
-
内存池化技术
ByteBuf buffer = Unpooled.copiedBuffer("Hello", CharsetUtil.UTF_8);
-
② ChannelPipeline(处理链)
-
由多个
ChannelHandler
组成的处理流水线 -
数据流向:
入站: Channel → Handler1 → Handler2 → ... 出站: ... → Handler2 → Handler1 → Channel
③ Bootstrap(引导类)
-
ServerBootstrap:服务端启动类
-
Bootstrap:客户端启动类
ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new MyHandler()); } });
三、Netty线程模型深度解析
1. Reactor模式变体
-
单线程模型:所有I/O操作由一个线程处理(仅测试使用)
-
多线程模型:一个Acceptor线程 + N个I/O线程
-
主从多线程模型(Netty默认):
-
Boss Group:处理连接请求
-
Worker Group:处理I/O操作
-
2. 最佳线程数配置公式
I/O线程数 = CPU核心数 × 2
(适用于一般I/O密集型场景)
四、实战:构建Echo服务器
1. 服务端代码实现
public class EchoServer {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new EchoServerHandler());
}
});
ChannelFuture f = b.bind(8080).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
// 业务处理器
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf in = (ByteBuf) msg;
System.out.println("收到消息: " + in.toString(CharsetUtil.UTF_8));
ctx.writeAndFlush(Unpooled.copiedBuffer("ECHO: " + in.toString(CharsetUtil.UTF_8), CharsetUtil.UTF_8));
}
}
2. 客户端测试
telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello Netty!
ECHO: Hello Netty!
五、Netty常见问题解决方案
1. 内存泄漏排查
-
现象:
LEAK: ByteBuf.release() was not called
-
解决:
-
使用
SimpleLeakAwareByteBuf
检测 -
确保每次write操作后调用
ReferenceCountUtil.release(msg)
-
2. 线程阻塞优化
-
错误写法:
channelRead() { Thread.sleep(5000); // 阻塞EventLoop线程 }
-
正确做法:将耗时操作提交到业务线程池
executorService.execute(() -> { // 耗时操作 ctx.writeAndFlush(result); });
3. 粘包/拆包处理
-
解决方案:
-
使用内置解码器:
pipeline.addLast(new LineBasedFrameDecoder(1024)); pipeline.addLast(new StringDecoder());
-
自定义协议(如:消息头包含长度字段)
-
六、性能调优关键参数
参数名 | 默认值 | 建议值 | 作用说明 |
---|---|---|---|
SO_BACKLOG | 128 | 1024 | 等待连接队列长度 |
WRITE_BUFFER_WATER_MARK | 32KB-64KB | 根据内存调整 | 写缓冲区水位线 |
ALLOCATOR | Pooled | Pooled | 使用内存池分配ByteBuf |
TCP_NODELAY | false | true | 禁用Nagle算法 |
七、学习路线建议
基础阶段:
掌握NIO编程模型
理解Reactor模式
完成简单Echo服务开发
进阶阶段:
研究编解码器(Protobuf/JSON)
掌握心跳机制与断线重连
学习Netty源码设计
高级应用:
实现自定义协议
网关类项目开发
与SpringBoot集成