0%

Netty的责任链

为了避免逻辑判断泛滥导致的拓展性受限问题,Netty 发明了 pipelinechannelHandler 。它通过责任链设计模式来组织代码逻辑,并且能够支持逻辑的动态添加和删除 ,Netty 能够支持各类协议的扩展,比如 HTTP,WebSocket,Redis,靠的就是 pipelinechannelHandler

结构

image-20210905211158604

在 Netty 整个框架里面,一条连接对应着一个 Channel,这条 Channel 所有的处理逻辑都在一个叫做 ChannelPipeline 的对象里面,ChannelPipeline 是一个双向链表结构,他和 Channel 之间是一对一的关系。

ChannelPipeline 里面每个节点都是一个 ChannelHandlerContext 对象,这个对象能够拿到和 Channel 相关的所有的上下文信息,然后这个对象包着一个重要的对象,那就是逻辑处理器 ChannelHandler

channelHandler 家族

image-20210905211319568

入站操作和数据由 ChannelInboundHandler处理。 在开始组装响应之前的所有的逻辑,都可以放置在 ChannelInboundHandler 里处理,它的一个最重要的方法就是 channelRead()。比如,我们在一端读到一段数据,首先要解析这段数据,然后对这些数据做一系列逻辑处理,最终把响应写到对端。

出站操作和数据将由ChannelOutboundHandler 处理。它是定义我们一端在组装完响应之后,把数据写到对端的逻辑,它里面最核心的一个方法就是 write()。比如,我们封装好一个 response 对象,接下来我们有可能对这个 response 做一些其他的特殊逻辑,然后,再编码成 ByteBuf,最终写到对端。

这两个子接口分别有对应的默认实现,ChannelInboundHandlerAdapterChanneloutBoundHandlerAdapter,它们分别实现了两大接口的所有功能,默认情况下会把读写事件传播到下一个 handler

事件传播

Netty通过责任链设计模式来组织代码逻辑,所谓的事件传播其实就是事件在ChannelPipeline上移动。

可以看到ChannelPipeline是由一系列ChannelHandlers组成,其还提供了通过自身传播事件的方法,当进站事件触发时,其从ChannelPipeline的头部传递到尾部,而出站事件会从右边传递到左边。

当管道传播事件时,其会确定下一个ChannelHandler的类型是否与移动方向匹配,若不匹配,则会跳过并寻找下一个,直至找到相匹配的ChannelHandler(一个处理器可以会同时实现ChannelInboundHandlerChannelOutboundHandler)。

img

关于ChannelInboundHandlerChanneloutBoundHandler的传播顺序的不同,可以看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
serverBootstrap
.childHandler(new ChannelInitializer<NioSocketChannel>() {
protected void initChannel(NioSocketChannel ch) {
// inBound,处理读数据的逻辑链
ch.pipeline().addLast(new InBoundHandlerA());
ch.pipeline().addLast(new InBoundHandlerB());

ch.pipeline().addLast(new OutBoundHandlerD());

ch.pipeline().addLast(new InBoundHandlerC());

// outBound,处理写数据的逻辑链
ch.pipeline().addLast(new OutBoundHandlerE());
}
});

在该例子中,pipeline 的执行顺序是:InBoundHandlerA->InBoundHandlerB()->InBoundHandlerC()->OutBoundHandlerE()

channelPipeline是双向链表,inBoundHandler 的事件通常只会传播到下一个 inBoundHandleroutBoundHandler 的事件通常只会传播到下一个 outBoundHandler,两者相互不受干扰。

inBoundHandler 的执行顺序与我们实际的添加顺序相同,而 outBoundHandler 则相反。