Netty 初学者学习笔记 🚀
Netty 是一个 高性能 Java NIO 网络框架,用于构建 高并发、低延迟的 TCP/UDP/HTTP 服务器和客户端,广泛应用于 RPC(如Dubbo)、游戏服务器、实时通信(WebSocket)、大数据传输(如Kafka) 等领域。
📌 1. Netty 核心概念
🔹 1.1 Netty vs Java NIO
| 对比项 | Java NIO | Netty |
|---|---|---|
| API易用性 | 复杂(Selector、Channel、Buffer) | 封装简化,提供更易用的Handler机制 |
| 性能优化 | 需手动管理内存、事件驱动优化 | 零拷贝、事件循环、内存池优化 |
| 协议支持 | 需额外实现HTTP/WebSocket等 | 内置多种协议支持 |
| 生态 | 基础API | 完善的社区支持(Dubbo、RocketMQ) |
🔹 1.2 核心组件
| 组件 | 作用 |
|---|---|
| EventLoop | 事件循环,处理 I/O 事件(连接、读写) |
| Channel | 网络连接(如 NioSocketChannel) |
| ChannelHandler | 处理业务逻辑(编解码、逻辑处理) |
| Pipeline | 一个pipeline管理多个 ChannelHandler |
| ByteBuf | Netty 的高性能字节缓存(替代 ByteBuffer) |
为了更好地理解,下面找了一张图,红色圆圈的Socket包含组件Channel,负责客户端与服务端的通信
📌 2. 快速搭建一个 Netty 服务端
🔹 2.1 依赖引入(Maven)
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.86.Final</version>
</dependency>
🔹 2.2 Netty服务端代码
public class NettyServer {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
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) {
// 1. 解决粘包拆包:消息头(4字节长度)+ 消息体
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(
1024, // max frame length
0, // length field offset (header starts at 0)
4, // length field size (int = 4 bytes)
0, // length adjustment
4 // bytes to strip (after decoding)
));
// 2. 自定义业务处理器
ch.pipeline().addLast(new ServerHandler());
}
});
ChannelFuture future = bootstrap.bind(8080).sync();
System.out.println("Netty 服务端启动,监听 8080 端口...");
future.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
🔹 2.3 自定义 Handler(处理消息)
public class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// 收到的数据(自动转为 ByteBuf)
ByteBuf buf = (ByteBuf) msg;
String received = buf.toString(CharsetUtil.UTF_8);
System.out.println("收到客户端消息: " + received);
// 回写相同数据
ByteBuf response = Unpooled.copiedBuffer("Server: " + received, CharsetUtil.UTF_8);
ctx.writeAndFlush(response);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
📌 3. 快速搭建一个 Netty 客户端
🔹 3.1 客户端代码
public class NettyClient {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
// 1. 客户端编码:消息头(4字节长度)+ 消息体
ch.pipeline().addLast(new LengthFieldPrepender(4)); // 长度字段占4字节
// 2. 解码(与服务端一致)
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(
1024, 0, 4, 0, 4
));
// 3. 自定义业务处理器
ch.pipeline().addLast(new ClientHandler());
}
});
ChannelFuture future = bootstrap.connect("127.0.0.1", 8080).sync();
System.out.println("Netty 客户端连接成功...");
// 模拟发送多条消息(测试粘包拆包)
for (int i = 0; i < 5; i++) {
String msg = "Message #" + i;
ByteBuf buf = Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8);
future.channel().writeAndFlush(buffer);
Thread.sleep(500);
}
future.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
}
}
🔹 3.2 客户端 Handler
public class ClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) {
// 连接建立后发送消息
ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, Netty!", CharsetUtil.UTF_8));
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf buf = (ByteBuf) msg;
System.out.println("收到服务端回复: " + buffer.toString(CharsetUtil.UTF_8));
}
}
📌 4. Netty 高级特性
🔹 4.1 编解码(如处理 HTTP 协议)
pipeline.addLast(new HttpServerCodec()); // HTTP 编解码
pipeline.addLast(new HttpObjectAggregator(65536)); // 聚合 HTTP 请求
pipeline.addLast(new MyHttpHandler()); // 自定义业务处理器
🔹 4.2 粘包/拆包解决
// 固定长度解析
pipeline.addLast(new FixedLengthFrameDecoder(10));
// 分隔符解析(如 \n)
pipeline.addLast(new DelimiterBasedFrameDecoder(1024, Unpooled.wrappedBuffer("\n".getBytes())));
🔹 4.3 心跳检测(避免连接闲置)
pipeline.addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS)); // 5秒读空闲检测
pipeline.addLast(new MyHeartbeatHandler()); // 处理心跳
📌 5. 常见面试题
- Netty 的线程模型是什么?
- Reactor 多线程模型(BossGroup + WorkerGroup)。
- ByteBuf 和 ByteBuffer 的区别?
ByteBuf支持动态扩容、引用计数、零拷贝优化。
- 如何解决 TCP 粘包问题?
- 使用
LengthFieldBasedFrameDecoder或自定义协议(如header + body)。
- 使用
🌟 总结
- Netty 通过 事件驱动 + 异步非阻塞 实现高性能。
- 核心组件:
EventLoop、Channel、Pipeline、ByteBuf。 - 适用场景: 高并发服务器、RPC、实时通信(如WebSocket)。