一,设计模式-责任链模式
责任链模式(Chain of Responsibility Pattern )为请求创建了一个处理对象的链。
发起请求和具体处理请求的过程进行解耦,职责链上的处理者负责处理请求,客户只需要将
请求发送到职责链上即可,无须关心请求的处理细节和请求的传递。
二,实现责任链模式
责任链模式有四个要素:
- 处理器的抽象类
- 具体的处理器实现类
- 保存处理器信息
- 处理执行
三,Netty中的ChannelPipeline责任链
Pipeline管道 保存了通道所有处理器信息。创建新Channel 时自动创建一个专有的 pipeline。入站事件 和出站 操作 会调用 pipeline 上的处理器
思考:
- 入站事件和出站事件是什么意思?
- handler 处理器是什么,有什么作用?
- P ipeline 如何维护 handler 的。
- handler 的执行。
1.入站事件和出站事件
入站事件:通常指 I/O 线程生成了入站数据。
(通俗理解:从 socket 底层自己往上冒上来的事件都是入站)比如EventLoop 收到 selector 的 OP_READ 事件, 入站处理器 调用socketChannel.read(ByteBuffer)接收到数据后,这将导致通道的 ChannelPipeline 中包含的下一个 入站处理器 中的channelRead 方法被调用。
inbound 入站事件
出站事件:经常是指 I/O 线程执行实际的输出操作。
(通俗理解:想主动往socket 底层操作的事件的都是出站)比如bind 方法用意是请求 server socket 绑定到给定的 SocketAddress ,这将导致通道的ChannelPipeline 中包含的下一个 出站处理器 中的 bind 方法被调用。
outbound出站事件
2.Pipeline中的handler是什么
1)ChannelHandler
用于处理 I/O 事件或拦截 I/O 操作,并转发到 ChannelPipeline 中的下一个处理器。
这个顶级接口定义功能很弱,实际使用时会去实现下面两大子接口:
- 处理入站I/O 事件的 ChannelInboundHandler
- 处理出站 I/O 操作的 ChannelOutboundHandler
2)适配器类
为了开发方便,避免所有 handler 去实现一遍接口方法, Netty 提供了简单的实现类。
- ChannelInboundHandlerAdapter 处理入站 I/O 事件
- ChannelOutboundHandlerAdapter 来处理出站 I/O 操作
- ChannelDuplexHandler 来支持同时处理入站和出站事件
3)ChannelHandlerContext
实际存储在 Pipeline 中的对象并非 ChannelHandler ,而是ChannelHandlerContext上下文对象。
将handler ,包裹在上下文对象中,通过上下文对象与它所属的 ChannelPipeline 交互,向上或向下传递事件或者修改 pipeline 都是通过上下文对象。
3.维护Pipeline 中的 handler
ChannelPipeline是线程安全的, ChannelHandler 可以在任何时候添加或删除。
例如,你可以在即将交换敏感信息时插入加密处理程序,并在交换后删除它。
一般操作,初始化的时候增加进去,较少删除。下面是Pipeline 中管理 handler 的 API
四,总结
Pipeline&Channel&Eventloop的关系
Pipeline内部结构
用户在管道中有一个或多个 channelhandler 来接收 I/O 事件 例如读取 和请求 I/O 操作 例如写入和关闭 。
一个典型的服务器在每个通道的管道中都有以下处理程序,但是根据协议和业务逻辑的复杂性和特征,可能会有所不同
- 协议解码器:将二进制数据 例如 ByteBuf 转换为 Java 对象。
- 协议编码器:将 Java 对象转换为二进制数据。
- 业务逻辑处理程序:执行实际的业务逻辑 例如数据库访问 。
责任链设计模式的运用,保证了Netty 的高度可拓展性!