Pipeline模式(netty源码死磕6)

精进篇:netty源码死磕6  html

巧夺天工——Pipeline模式揭秘设计模式


1. 巧夺天工——Pipeline模式揭秘

1.1. Pipeline模式简介

管道的发名者叫,Malcolm Douglas McIlroy,他也是Unix的建立者,是Unix文化的缔造者之一。架构

40年前,Unix操做系统横空出世,Unix不只仅带来了一个操做系统,还创造C语言,Socket,开源,黑客等等文化,这些文化影响着整个计算机世界的文明,直到今天。app

若是说Unix是计算机文明中最伟大的发明,那么,Unix下的Pipe管道就是跟随Unix所带来的另外一个伟大的发明。管道的出现,解决的就是让不一样功能的程序能够互相连统统讯,从而可让软件开发,程序开发更加的“高内聚,低耦合”,从而可让程序“Do one thing, Do it well”,从而可让程序“Keep it Simple Stupid”等等,这一哲学引影了一代又一代的软件架构,直到今天的云计算。ide

管道模型,是一种“链式模型”,用来串接不一样的程序或者不一样的组件,让它们组成一条直线的工做流。这样给定一个完整的输入,通过各个组件的前后协同处理,获得惟一的最终输出。编码

1.2. Pipeline模式应用场景

简单的说,管道模型的典型应用场景,能够用一个形象的比方,有点相似像富士康那么的工厂生产线。云计算

管道模型包含两个部分:pipeline 管道、valve 阀门。操作系统

pipeline 管道,能够比做车间生产线,在这里可认为是容器的逻辑处理总线。设计

valve 阀门,能够比做生产线上的工人,负责完成各自的部分工做。 阀门也能够叫作Handler 处理者。netty

1.3. Tomcat中的Pipeline模式

在咱们很是熟悉的Web容器Tomcat中,一个请求,首先被Connector接受到。而后,会将请求交给Container,Container处理完了以后将结果返回给Connector 。

Tomcat中,Container包含了Engine、Host、Context、Wrapper几个内部的子容器元素。

这几个子容器元素的功能,赘述以下:

Engine:表明一个完整的 Servlet 引擎,能够包含多个Host。它接收来自Connector的请求,并决定传给哪一个Host来处理,获得Host处理完的结果后,返回给Connector。

Host:表明一个虚拟主机,一个Host能运行多个应用,它负责安装和展开这些应用,每一个Host对应的一个域名。

Context:一个Context表明一个运行在Host上的Web应用

Wrapper: 一个Wrapper 表明一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。

wps8A0D.tmp

在一个用户请求过来后,Tomcat中的每一级子容器,都对应于一个阀门Valve(注意:这个单词不是value,有一个字母的差异)。Tomcat接受请求以后,请求从被接受,被分发,被处理,到最后转变成http响应,会经过以下的阀门序列。


wpsE81D.tmp

这些阀门(Valve)经过invoke(next)方法彼此串联起来,最终构成的执行顺序,构成一个管道。

Pipeline模式,在设计模式中,属于责任链模式的一种。在Tomcat的Pipeline模式中。从Engine到Host再到Context一直到Wrapper,都是经过同一个责任链,来传递请求。

1.4. Netty中的Pipeline模式

看完前面的《Netty 源码(ChannelHandler 死磕)》一文,你们对Netty的Pipeline已经有初步的了解。

这里再简单的回顾一下。

一个Channel,拥有一个ChannelPipeline,做为ChannelHandler的容器。

可是一个ChannelHandler,不能直接放进Pipeline中,必须包裹一个AbstractChannelHandlerContext 的上下文环境。

在初始化Netty的Channel时,须要将Handler加载到Pipeline中。

假定加载三个Handler,分别负责解码、业务、编码。三个Handler加载到ChannelPipeline的参考代码以下:

@Override
public void initChannel(SocketChannel ch) throws Exception
{
    ChannelPipeline p = ch.pipeline();
    p.addLast(new DecoderHandler());
    p.addLast(new BusinessHandler());
    p.addLast(new EncoderHandler());
}

Netty中Channel加完Hander以后,Pipeline的容器内容图以下:

wps4A81.tmp

Pipeline中不直接加入Handler,而是须要进行包裹。对应于Decoder、Business、Encoder三个Hander,分别建立三个默认的上下文包裹器(DefaultContext )。DefaultContext 的具体实现类,在Netty中,是DefaultChannelHandlerContext。

除此以外,Pipeline的头尾,各有一个特别的上下文Context 。这两个Hander Context ,不是默认的DefaultContext 。分别有本身的类型。

1.5. Context的类型

在Pipeline中头尾,分别各有一个特别的HandlerContext——简称Head和Tail。Head的类型是HeadContext。Tail的类型是TailContext。这两种类型,和DefaultChannelHandlerContext类型,都是AbstractChannelHandlerContext的子类。

wpsABAD.tmp


Head和做用是什么呢?

Head上下文包裹器的主要做用: 主要是做为入站处理的起点。数据从Channel读入以后,一个入站数据包从Channel的事件发送出来,首先从Head开始,被后面的全部的入站处理器,逐个进行入站处理。

大体的入站流程以下图:

wpsDD3.tmp

注意,TailContext,其实也是一个入站处理器。先按下不表,待会详细阐述。

Tail的做用是什么呢?

Tail上下文包裹器的主要做用: 主要是做为出站处理的起点。当全部的入站处理器,都处理完成后,开始出站流程。须要出站的数据包,首先从Tail开始,被全部的出站处理器上下文Context中的Hander逐个进行处理。而后将处理结果,写入Channel中。

wps63B4.tmp

注意,HeadContext,其实也是一个出站处理器。先按下不表,待会详细阐述。

Tail和Head内部,没有包裹其余的内部Handler成员。这一点,是与默认的上下文包裹器DefaultChannelHandlerContext不一样的地方。

TailContext自己实现了ChannelInboundHandler 接口的方式,能够完成入站处理的操做,做为一个入站处理器使用。

HeadContext自己,实现了ChannelOutboundHandler 接口的方式,能够完成出站处理的操做,完成最终的出站处理操做。


1.6. Pipeline模式的优势:

总结一下Pipeline模式的优势,以下:

一、下降耦合度。它将请求的发送者和接收者解耦。

二、简化了Handler处理器。使得处理器不须要不须要知道链的结构。也就是Handler处理器能够是无状态的。与责任链(流水线)相关的状态,交给了Context去维护。

三、加强给对象指派职责的灵活性。经过改变链内的成员或者调动它们的次序,容许动态地新增或者删除责任。

四、 增长新的请求处理器很方便。

1.7. 小结

本节从宏观上,解读了什么是Netty的pipeline。

下一篇:Pipeline的入站流程和出站流程