Java学习总结(2.2.2) 责任链模式
设计模式 - 责任链模式
责任链模式( Chain of Responsibility Pattern)为请求创建了一个处理对象的链。
发起请求和具体处理请求的过程进行解耦:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递。
实现责任链
实现责任链模式4个要素:
处理器抽象类、具体的处理器实现类、保存处理器信息、处理执行
Netty中的ChannelPipeline责任链
Pipeline管道保存了通道所有处理器信息。创建新 channele时自动创建一个专有的 pipeline入站事件和出站操作会调用 pipeline上的处理器
入站事件与出站事件
入站事件:通常指I/O线程生成了入站数据。(通俗理解:从 socket底层自己往上冒上来的事件都是入站)比如 Eventloop收到 selector的OP_READ事件,入站处理器调用 socketChannel.read( Bytebuffer)接收到数据后,这将导致通道的 Channelpipeline中包含的下一个中的 channelread方法被调用。
出站事件:经常是指O线程执行实际的输出操作。(通俗理解:想主动往 socket底层操作的事件的都是出站)比如bind方法用意是请求 server socket绑定到给定的 Socketaddress,这将导致通道的Channelpipeliner中包含的下一个出站处理器中的bind方法被调用。
Netty中事件的定义
inbound入站事件
事件 | 描述 |
fireChannelRegistered | channel注册事件 |
fireChannelUnregistered | channel解除注册事件 |
firechannelActive | channel活跃事件 |
fireChannelInactive | channel非活跃事件 |
fireExceptionCaught | 异常事件 |
fireUserEventTriggered | 用户自定义事件 |
fireChannelReadchanne | 读事件 |
fireChannelReadCompletechanne | 读完成事件 |
fireChannelWritabilityChangedChannel | 写状态变化事件 |
outbound出站事件
事件 | 描述 |
bind | 端口绑定事件 |
connect | 连接事件 |
disconnect | 断开连接事件 |
close | 关闭事件 |
deregister | 解除注册事件 |
flush | 刷新数据到网络事件 |
read | 读事件,用于注册OP_READ到 selector |
write | 写事件 |
writeAndFlush | 写出数据事件 |
Pipeline中的handler是什么
Channelhandler:
用于处理I/O事件或拦截I/O操作,并转发到 ChannelPipeline中的下一个处理器。
这个顶级接口定义功能很弱,实际使用时会去实现下面两大子接口:
处理入站I/O事件的 Channellnboundhandler、处理出站I/O操作的 Channeloutboundhandler
适配器类:
为了开发方便,避免所有 handler去实现一遍接口方法,Netty提供了简单的实现类:
ChannellnboundHandlerAdapter处理入站I/O事件
ChannelOutboundHandlerAdapter来处理出站I/O操作
Channelduplexhandler来支持同时处理入站和出站事件
Channelhandlercontext:
实际存储在 Pipeline中的对象并非 Channelhandler,而是上下文对象。将 handler,包裏在上下文对象中,通过上下文对象与它所属的 Channelpipeline交互,向上或向下传递事件或者修改 pipeline都是通过上下文对象。
维护Pipeline中的handler
Channelpipeline是线程安全的, Channelhandleri可以在任何时候添加或删除。例如,你可以在即将交换敏感信息时插入加密处理程序,并在交换后删除它。一般操作,初始化的时候增加进去,较少删除。下面是 Pipeline中管理 handlers的API
方法名称 | 描述 |
addFirst | 最前面插入 |
addLast | 最后面插入 |
addBefore | 插入到指定处理器前面 |
addAfter | 插入到指定处理器后面 |
remove | 移除指定处理器 |
removeFirst | 移除第一个处理器 |
removeLast | 移除最后一个处理器 |
replace | 替换指定的处理器 |
handler的执行分析
ChannelDuplexHandler 5 |
Outbound Handler 4 |
Outbound Handler 3 |
Inbound Handler 2 |
Inbound Handler 1 |
当入站事件时,执行顺序是1、2、3、4、5
当出站事件时,执行顺序是5、4、3、2、1
在这一原则之上, Channelpipeline在执行时会进行选择3和4为出站处理器,因此入站事件的实际执行是:1、2、5
1和2为入站处理器,因此出站事件的实际执行是:5、4、3
不同的入站事件会触发 handler.不同的方法执行:
上下文对象中fire开头的方法,代表入站事件传播和处理其余的方法代表出站事件的传播和处理。
分析 registered入站事件的处理
1)bind(端口):AbstractBootstrap
2)创建和初始化Channel
3)注册到EventLoop中的Selector上
注2:
通道创建时构建一个 pipeline,头尾分别是 Head Context..Tail Context
init()增加了一个 Channellnitializer,这个 handler用于通道初始化,我们自己的相关初始化定义都是通过它执行的。
注3:
config(). group(). register() registered成功之后
触发 Channellnitializer.channelRegistered
初始化 Handler执行一次之后,会把自己从pipeline中除掉
分析bind出站事件的处理
1) bind(端口): Abstractbootstrap
2) 创建和初始化Channel
3) 注册到 EventLoop中的 Selector上
4) dobind0()-> channel.bind
5) pipeline.bind
出站操作
6) ServerSocketChannel
7) HeadContext.bind
8) AbstractUnsafe.bind
9) NioServerSocketChannel.doBind
分析 accept入站事件的处理
1) EventLoop轮询到accept事件
2) NioMessageUnsafe.read
3) NioServerSocketChannel.doReadMessages
4) 传播fireChannelRead事件
入站操作自底向上
5) 完成注册后的ChannlPipeline
6)channelRead
这是一个分配的过程, main Group负责accept,然后分配sub Group负责read
分析read入站事件的处理
pipeline分析的关鍵4要素:
什么事件、有哪些处理器、哪些会被触发、执行顺序
1) EventLoop轮询到op_read事件
2) NioByteUnsafe.read 读取内容
3) fireChannelRead、readComplete
入站操作
4) socketChannel的ChannelPipeline
小结
用户在管道中有一个或多个 channelhandler来接收I/O事件(例如读取)和请求I/O操作(例如写入和关闭)。
一个典型的服务器在每个通道的管道中都有以下处理程序,但是根据协议和业务逻辑的复杂性和特征,可能会有所不同:
协议解码器一一将二进制数据(例如 Bytebuf转换为Java对象。
协议编码器一一将Java对象转换为二进制数据。
业务逻辑处理程序一一执行实际的业务逻辑(例如数据库访问)。
责任链设计模式的运用,保证了Netty的高度可拓展性!
每日一句
博客分组
标签云
- 最近综合
- 情绪巨婴是什么 12.18
- 普通蛋糕做法 05.31
- 玉米烤肠芝士面包做法 05.31
- Mysql安装教程 - 绿色版 06.18
- 我们学习知识为什么总是忘记呢?【学习金字塔】 05.12
- Typora开发版⽆法使⽤解决⽅法 05.04
- 为什么无知者越自信? -- 达克效应 05.10
- 马斯洛需求层次理论 04.29
- 随机综合
- Java学习总结(2.1.1) TCP/UDP协议 04.17
- Java学习总结(2.2.2) 责任链模式 04.20
- Java学习总结(1.2.2) 线程安全之原子操作 03.20
- 中间件1.2.2-ActiveMQ支持的消息协议讲解 04.23
- iPhone 6与iPhone 6 Plus正式开放预订 09.17
- 马斯洛需求层次理论 04.29
- Java学习总结(2.1.3) NIO非阻塞网络编程三大核心理念 04.17
- 中间件1.2.4-ActiveMQ持久化原理和事务机制 04.29