Netty基础招式——ChannelHandler的最佳实践(一)

简介: Netty基础招式——ChannelHandler的最佳实践(一)

1.什么是ChannelHandler和ChanneIPipeline


ChannelHandler是一个包含所有应用处理逻辑的容器载体,用来对Netty的输入输出数据进行加工处理。


比如数据格式转换、异常处理等


ChannelPipeline 则是 ChannelHandler 的容器载体,负责以链式的形式调度各个注册的ChannelHandler。


我们回顾下之前介绍过的Netty逻辑架构,观察下ChannelPipeline和ChannelHandler的位置。

87.png


再从局部放大,可以更加明确地看到ChannelPipeline和ChannelHandler的作用。


88.png


如上图所示,当EventLoop中监听到事件后,会对I/O事件进行处理。而这个处理,就是交给ChannelPipeline进行,更严格地说,是交给ChannelPipeline中的各个ChannelHandler按照一定的顺序进行处理。


根据数据的流向,Netty把ChannelHandler分为2类,InboundHandler和OutboundHandler。

89.png


如上图所示,Netty接收到数据后,经过若干 InboundHandler 处理后接收成功。如果要输出数据,就需要经过若干个 OutboundHandler 处理完成后发送。


比如,我们经常需要对接收到的数据进行解码,就是在某一个专门decode的InboundHandler中处理的。如果要发送数据,往往需要编码,就是在某一个专门encode的OutBoundHandler中处理的。


值得一提的是,虽然我们在使用Netty时,直接打交道的是ChannelPipeline和ChannelHandler,但是,它们之间有一座“隐形”的桥梁,名字叫做ChannelHandlerContext。


顾名思义,ChannelHanderContext就是ChannelHandler的上下文,每个 ChannelHandler 都对应一个 ChannelHandlerContext。


每一个 ChannelPipeline 都包含多个 ChannelHandlerContext,所有 ChannelHandlerContext 之间组成了双向链表。如下图所示。

90.png


其中,有两个特殊的ChannelHandlerContext,分别是HeadContext和TailContext,表示双向链表的头尾节点。

91.png


从类图上可以看到,HeadContext同时实现了ChannelInboundHandler和ChannelOutboundHandler。因此,HeadContext在读取数据时作为头节点,向后传递InBound事件,同时,在写数据时作为尾节点,处理最后的OutBound事件。


TailContext只实现了ChannelInboundHandler。它在InBound事件传递的末尾,负责处理一些资源释放的工作。在OutBound事件传递的第一个节点,不做任何处理,仅仅传递OutBound事件给prev节点。


而我们平时自定义的ChannelHandler,就是插在这两个头尾节点之间的。


至此,我们对ChannelHandler和ChannelPipeline有了基本的认识。具体到实践上,我们该如何正确地使用ChannelHandler呢?


对ChannelHandler的使用,必须先了解ChannelHandler的事件传播机制和异常处理机制。


2.ChanneIHandler的事件传播机制


前面我们提到了Netty中的两种事件类型,Inbound事件和Outbound事件,分别对应InboundHandler和OutbountHandler进行处理。


当我们使用Netty进行开发的时候,必须了解Inbound事件和Outbound事件在ChannelPipeline中如何进行“事件传播”,注册InboundHandler和OutboundHandler的顺序有什么影响。


话不多说,我们先来一个demo直观地感受一下。


自定义一个ChannelInboundHandler


92.png


自定义一个ChannelOutboundHandler


93.png


简单组装一下EchoPipelineServer,特别注意一下 6个handler 的注册顺序。


94.png


然后我们通过命令行简单访问一下这个Netty Server


curl localhost:8081


可以看到控制台的如下输出


95.png


这样就清楚了事件传播顺序:


- 对于Inbound事件,InboundHandler的处理顺序是和注册顺序一致

- 对于Outbound事件,OutboundHandler的处理顺序和注册顺序相反


结合上一节说的HeadContext和TailContext,我们画个图来更直观地看一下这个ChannelPipeline中的handler构建顺序是怎样的。


96.png



在上面的ChannelInitializer中,我们按需添加了3个InboundHandler和3个OutboundHandler。所以,在头节点HeadContext和TailContext之间,有序构成了双向链表。


而InboundHandler3中,通过调用 ctx.channel.writeAndFlush( msg ) 方法,将消息从TailContext开始,依据OutboundHandler的路径向HeadContext方向传播出去。具体可以看下DefaultChannelPipeline类中的实现


97.png


虽然这里是双向链表,但是无论是Inbound事件还是Outbound事件,在按序访问链表节点时,会根据事件类型进行过滤。
目录
相关文章
|
4月前
|
编解码 开发者
Netty Review - 深入理解Netty: ChannelHandler的生命周期与事件处理机制
Netty Review - 深入理解Netty: ChannelHandler的生命周期与事件处理机制
60 0
|
4月前
|
前端开发 UED
Netty Review - Netty自动重连机制揭秘:原理与最佳实践
Netty Review - Netty自动重连机制揭秘:原理与最佳实践
93 0
|
5月前
|
网络协议 Java 容器
《跟闪电侠学Netty》阅读笔记 - ChannelHandler 生命周期
《跟闪电侠学Netty》阅读笔记 - ChannelHandler 生命周期
45 0
《跟闪电侠学Netty》阅读笔记 - ChannelHandler 生命周期
|
7月前
|
存储 前端开发 Java
Netty 爱好者必看!一文详解 ChannelHandler 家族,助你快速掌握 Netty 开发技巧!
Netty 爱好者必看!一文详解 ChannelHandler 家族,助你快速掌握 Netty 开发技巧!
133 0
|
10月前
|
移动开发 安全 前端开发
Netty实战(十二)预置的ChannelHandler和编解码器(二)
HTTPS、WebSocket的添加使用和大型数据写入以及几种常见的序列化)
60 0
|
10月前
|
安全 Java 关系型数据库
Netty实战(十一)预置的ChannelHandler和编解码器(一)
作为一个通讯框架,通讯数据的安全性也是不可或缺的一部分。一般常见的像TLS/SSL这样的安全协议我们都应该熟悉。 我们在访问安全网站时都遇到过这些协议,但是它们也可用于其他不是基于HTTP的应用程序,如安全SMTP(SMTPS)邮件服务器甚至是关系型数据库系统。
97 0
|
10月前
|
存储 缓存 安全
Netty实战(六)ChannelHandler和ChannelPipeline
ChannelHandler 的生命周期发生在ChannelHandler被添加到 ChannelPipeline 中或者被从 ChannelPipeline 中移除时。这些方法中的每一个都接受一个 ChannelHandlerContext 参数
111 0
|
编解码 缓存 安全
【Netty】ChannelHandler和codec
前面学习了Netty的codec框架,下面接着学习ChannelHandler与codec之间的关联。
105 0
【Netty】ChannelHandler和codec
|
8月前
|
监控 Java Linux
由浅入深Netty基础知识NIO网络编程1
由浅入深Netty基础知识NIO网络编程
42 0
|
8月前
|
缓存 安全 Java
由浅入深Netty基础知识NIO三大组件原理实战 2
由浅入深Netty基础知识NIO三大组件原理实战
48 0