推荐阅读:
【01】Netty从0到1系列之I/O模型
【02】Netty从0到1系列之NIO
【03】Netty从0到1系列之Selector
【04】Netty从0到1系列之Channel
【05】Netty从0到1系列之Buffer(上)
【06】Netty从0到1系列之Buffer(下)
【07】Netty从0到1系列之零拷贝技术
【08】Netty从0到1系列之整体架构、入门程序
【09】Netty从0到1系列之EventLoop
【10】Netty从0到1系列之EventLoopGroup
【11】Netty从0到1系列之Future
【12】Netty从0到1系列之Promise
【13】Netty从0到1系列之Netty Channel
【14】Netty从0到1系列之ChannelFuture
【15】Netty从0到1系列之CloseFuture
【16】Netty从0到1系列之Netty Handler
一、Netty Pipeline:责任链模式的核心实现
1.1 Pipeline是什么?
Pipeline 是 Netty 框架中的核心组件,它采用责任链模式来组织和管理所有的 ChannelHandler。Pipeline 定义了数据在网络通道中的处理流程,负责将入站和出站事件传递给正确的处理器,并确保处理器的执行顺序。
在 Netty 的高性能网络编程模型中,ChannelPipeline 是事件流动的“高速公路”和处理器调度的“指挥中枢”。它与 ChannelHandler 紧密协作,构成了 Netty 责任链模式 + 事件驱动的核心架构。
Pipeline 的核心特性:
- 责任链模式:多个 Handler 组成处理链,每个 Handler 专注特定功能
- 双向处理:支持入站(Inbound)和出站(Outbound)处理流程
- 动态管理:可以运行时添加、移除和替换 Handler
- 线程安全:保证在多线程环境下的安全操作
- 事件传播:负责事件在 Handler 之间的传递和控制
1.2 Pipeline的架构设计
为了更好地理解 Pipeline 的工作原理,我们先来看一下它的整体架构:

Pipeline全景图:

🌟 核心定位:
- ChannelPipeline 是一个双向链表构成的处理流水线
- 它管理 ChannelHandler 的执行顺序,驱动 I/O 事件在处理器间流动
1.3 核心概念
1.3.1 ChannelPipeline 是什么?
ChannelPipeline 的实现是一个 ChannelHandlerContext(包装了 ChannelHandler) 组成的双向链表.
- 默认在读的时候,会自动添加一个
head、tail的channelHandler.
- 每个
Channel都有且仅有一个Pipeline - 它在
Channel创建时自动创建 - 用于组织
ChannelHandler,形成处理链
✅ 关键特性:
- 线程安全:可在任意线程中添加/删除
Handler- 动态修改:支持运行时调整处理流程
- 事件路由:决定事件如何在
Handler间传播
// ChannelPipeline核心代码
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);
tail = new TailContext(this);
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
添加核心代码
private void addFirst0(AbstractChannelHandlerContext newCtx) {
AbstractChannelHandlerContext nextCtx = head.next;
newCtx.prev = head;
newCtx.next = nextCtx;
head.next = newCtx;
nextCtx.prev = newCtx;
}

// 类继承关系
public interface ChannelHandlerContext extends AttributeMap, ChannelInboundInvoker, ChannelOutboundInvoker {
}

@Override
public ChannelHandlerContext fireChannelRead(final Object msg) {
invokeChannelRead(findContextInbound(MASK_CHANNEL_READ), msg);
return this;
}
-
入站处理器中,
ctx.fireChannelRead(msg)是 调用下一个入站处理器; -
ctx.channel().write(msg);, 从链表尾部触发【后续出站处理执行】 -
ctx.write(msg, promise) 的调用也会 触发上一个出站处理器- 注意: 是
ChannelHandler添加顺序的上一个处理器
- 注意: 是
[!note]
- ctx.channel.write(msg) 和 ctx.write(msg, promise)
- ctx.channel.write(msg)是从
尾部开始查找【出站顺序】- ctx.write(msg, promise)是从
当前处理器的上一个出站处理器
1.3.2 ChannelHandlerContext:Pipeline 的“工位”
- 每个
Handler在Pipeline中都有一个对应的Context - 它是
Handler与Pipeline交互的桥梁
| 方法 | 说明 |
|---|---|
| ctx.fireChannelRead(msg) | 向下一个入站 Handler 传播 |
| ctx.write(msg) | 向前面的出站 Handler 传播 |
| ctx.pipeline() | 获取所属的 Pipeline |
| ctx.channel() | 获取所属的 Channel |
🌟 关键区别:
- ctx.write() vs channel.write()
- ctx.write():从当前节点向前传播
- channel.write():从Tail 节点开始向前传播(等价于 pipeline.write())
1.3.3 头尾节点(Head & Tail)
| 节点 | 类型 | 作用 |
|---|---|---|
| HeadContext | ChannelOutboundHandler + ChannelInboundHandler | - 入站:读取 Socket 数据 - 出站:执行底层 I/O 操作(如 write()) |
| TailContext | ChannelInboundHandler | - 处理未被消费的入站消息(自动释放) - 记录未处理的异常 |
- 入站: 读取
Socket数据
- 入站处理器通常是
ChannelInboundHandlerAdapter的子类,主要用来读取客户端数据,写回结果- 出站: 执行底层I/O操作(如write)
- 出站处理器通常是
ChannelOutboundHandlerAdapter的子类,主要对写回结果进行加工
1.4 事件传播机制深度解析
1.4.1 ✅ 入站事件(Inbound):Head → Tail
触发场景:
- 数据到达(channelRead)
- 连接建立(channelActive)
- 连接断开(channelInactive)
1.4.2 ✅ 出站事件(Outbound):Tail → Head
触发场景:
- 发送数据(write())
- 刷新缓冲(flush())
- 绑定地址(bind())
1.5 Pipeline核心API用法
1.5.1 基础的 Pipeline 配置和使用
package cn.tcmeta.pipeline;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
/**
* @author: laoren
* @description: 基础的 Pipeline 配置和使用
* @version: 1.0.0
*/
@Slf4j
public class BasicPipelineExample {
public static final int PORT = 8080;
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(2);
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 1. 添加编解码器
pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast("encoder", new StringDecoder(CharsetUtil.UTF_8));
// 2. 添加业务处理器
pipeline.addLast("firstHandler", new FirstHandler());
pipeline.addLast("secondHandler", new SecondHandler());
pipeline.addLast("thirdHandler", new ThirdHandler());
// 3. 打印pipeline结构
log.info("Pipeline structure: {}" , pipeline.names());
// 4. 动态添加处理器【演示使用】
ch.closeFuture().addListener(future -> {
log.info("连接关闭时Pipeline状态: {}", pipeline.names());
});
}
});
ChannelFuture future = bootstrap.bind(PORT).sync();
log.info("Server started at port {}", PORT);
future.channel().closeFuture().sync();
}catch (Exception e){
e.printStackTrace();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
// 第一个处理器
static class FirstHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("FirstHandler 处理: " + msg);
ctx.fireChannelRead(msg); // 传递给下一个处理器
}
}
// 第二个处理器
static class SecondHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String message = (String) msg;
System.out.println("SecondHandler 处理: " + message);
// 可以中断传递链
if ("skip".equals(message)) {
System.out.println("跳过后续处理");
// 不调用 ctx.fireChannelRead(),中断传递
} else {
ctx.fireChannelRead(message.toUpperCase()); // 修改后传递
}
}
}
// 第三个处理器
static class ThirdHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("ThirdHandler 收到: " + msg);
ctx.writeAndFlush("处理完成: " + msg); // 发送响应
}
}
}
12:03:00 [INFO ] [nioEventLoopGroup-3-2] c.t.p.BasicPipelineExample - Pipeline structure: [BasicPipelineExample$1#0, decoder, encoder, firstHandler, secondHandler, thirdHandler, DefaultChannelPipeline$TailContext#0]
FirstHandler 处理: laoren
SecondHandler 处理: laoren
ThirdHandler 收到: LAOREN
12:03:08 [INFO ] [nioEventLoopGroup-3-2] c.t.p.BasicPipelineExample - 连接关闭时Pipeline状态: [decoder, encoder, firstHandler, secondHandler, thirdHandler, DefaultChannelPipeline$TailContext#0]
1.5.2 动态管理Pipeline
package cn.tcmeta.pipeline;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
/**
* @author: laoren
* @date: 2025/9/3 12:07
* @description: 动态管理 Pipeline
* @version: 1.0.0
*/
@Slf4j
public class DynamicPipelineManagement {
private static class PipelineManagerHandler extends io.netty.channel.ChannelInboundHandlerAdapter {
public static final String COMPRESSION_HANDLER = "compressionHandler";
public static final String LOGGING_HANDLER = "loggingHandler";
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ChannelPipeline pipeline = ctx.pipeline();
if (msg instanceof String message) {
// 1. 动态添加处理器
if (message.startsWith("ADD_COMPRESSION") &&
pipeline.get(COMPRESSION_HANDLER) == null) {
pipeline.addAfter(ctx.name(), COMPRESSION_HANDLER, new CompressionHandler());
ctx.writeAndFlush("COMPRESSION ADD SUCCESS! \n");
return;
}
// 2. 动态移除处理器
if (message.startsWith("REMOVE_COMPRESSION")) {
if (pipeline.get(COMPRESSION_HANDLER) != null) {
pipeline.remove(COMPRESSION_HANDLER);
ctx.writeAndFlush("COMPRESSION Remove ok \n");
}
return;
}
// 3. 动态替换处理器
if (message.startsWith("REPLACE_LOGGING")) {
if (pipeline.get(LOGGING_HANDLER) != null) {
pipeline.replace(LOGGING_HANDLER, "enhancedLogging",
new EnhancedLoggingHandler());
ctx.writeAndFlush("Logging Handler Replace!\n");
}
return;
}
// 4. 查看当前Pipeline结构
if (message.startsWith("SHOW_PIPELINE")) {
ctx.writeAndFlush("Pipeline Struct: " + pipeline.names() + " \n");
return;
}
}
ctx.fireChannelRead(msg);
}
}
// 压缩处理器
public static class CompressionHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("压缩处理: " + msg);
ctx.fireChannelRead("COMPRESSED(" + msg + ")");
}
}
// 基础日志处理器
public static class LoggingHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("Logging: " + msg);
ctx.fireChannelRead(msg);
}
}
// 增强版日志处理器
public static class EnhancedLoggingHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("增强日志[" + System.currentTimeMillis() + "]: " + msg);
ctx.fireChannelRead(msg);
}
}
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
NioEventLoopGroup workerGroup = new NioEventLoopGroup(2);
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
log.info("channel id is : {}", ch.id());
// 1. 添加编解码器
pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
// 2. 添加业务处理器
pipeline.addLast("pipelineManagerHandler", new PipelineManagerHandler());
// 3. 添加日志处理器
// pipeline.addLast("logger", new io.netty.handler.logging.LoggingHandler());
}
});
// 绑定端口号
ChannelFuture future = bootstrap.bind(8080).sync();
log.info("Server started at port 8080");
// 等待关闭
future.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
客户端

服务器端

1.5.3 完整的 Pipeline 配置示例
package cn.tcmeta.pipeline;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.CharsetUtil;
public class CompletePipelineExample {
private static final int PORT = 8080;
private static final ByteBuf DELIMITER = Unpooled.copiedBuffer("\n", CharsetUtil.UTF_8);
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)
// 添加日志处理器(对ServerSocketChannel生效)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 1. 日志记录(第一个处理器)
pipeline.addLast("logging", new LoggingHandler(LogLevel.DEBUG));
// 2. 解决粘包/拆包问题
// 方案1: 基于分隔符
pipeline.addLast("frameDecoder",
new DelimiterBasedFrameDecoder(1024, DELIMITER));
// 方案2: 基于长度字段(二选一)
// pipeline.addLast("frameDecoder2",
// new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));
// pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
// 3. 编解码器
pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));
// 4. 业务处理器
pipeline.addLast("authHandler", new AuthenticationHandler());
pipeline.addLast("throttlingHandler", new ThrottlingHandler(1000)); // 1秒限流
pipeline.addLast("businessHandler", new BusinessLogicHandler());
pipeline.addLast("statsHandler", new StatisticsHandler());
// 5. 异常处理(通常放在最后)
pipeline.addLast("exceptionHandler", new GlobalExceptionHandler());
System.out.println("完整Pipeline配置: " + pipeline.names());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture future = bootstrap.bind(PORT).sync();
System.out.println("服务器启动在端口: " + PORT);
future.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
// 认证处理器
class AuthenticationHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof String message) {
if (message.startsWith("AUTH:")) {
// 处理认证逻辑
if ("valid_token".equals(message.substring(5))) {
ctx.fireChannelRead("认证成功: " + message);
} else {
ctx.writeAndFlush("认证失败\n");
return;
}
} else {
ctx.fireChannelRead(msg);
}
}
}
}
// 限流处理器
class ThrottlingHandler extends ChannelInboundHandlerAdapter {
private final long minInterval;
private long lastProcessTime;
public ThrottlingHandler(long minIntervalMs) {
this.minInterval = minIntervalMs;
this.lastProcessTime = 0;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
long currentTime = System.currentTimeMillis();
if (currentTime - lastProcessTime >= minInterval) {
lastProcessTime = currentTime;
ctx.fireChannelRead(msg);
} else {
ctx.writeAndFlush("请求过于频繁,请稍后重试\n");
}
}
}
// 业务逻辑处理器
class BusinessLogicHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof String) {
String response = processBusinessLogic((String) msg);
ctx.writeAndFlush(response + "\n");
}
}
private String processBusinessLogic(String message) {
// 模拟业务处理
return switch (message) {
case "time" -> "当前时间: " + System.currentTimeMillis();
case "stats" -> "服务器运行中";
default -> "回声: " + message;
};
}
}
// 统计处理器
class StatisticsHandler extends ChannelInboundHandlerAdapter {
private int messageCount = 0;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
messageCount++;
if (messageCount % 10 == 0) {
System.out.println("已处理 " + messageCount + " 条消息");
}
ctx.fireChannelRead(msg);
}
}
// 全局异常处理器
class GlobalExceptionHandler extends ChannelInboundHandlerAdapter {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.err.println("全局异常捕获: " + cause.getMessage());
ctx.writeAndFlush("服务器内部错误\n");
ctx.close();
}
}
【注意事项】: 注意处理器添加的顺序.
6235

被折叠的 条评论
为什么被折叠?



