精进篇:netty源码死磕6 

巧夺天工——Pipeline模式揭秘


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

1.1. Pipeline模式简介

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

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

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

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

1.2. Pipeline模式应用场景

简单的说,管道模型的典型应用场景,可以用一个形象的比方,有点类似像富士康那么的工厂生产线。

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

pipeline 管道,可以比作车间生产线,在这里可认为是容器的逻辑处理总线。

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

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 的装载、初始化、执行以及资源回收。

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

这些阀门(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的容器内容图如下:

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的子类。

Head和作用是什么呢?

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

大致的入站流程如下图:

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

Tail的作用是什么呢?

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

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

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

TailContext本身实现了ChannelInboundHandler 接口的方式,可以完成入站处理的操作,作为一个入站处理器使用。

HeadContext本身,实现了ChannelOutboundHandler 接口的方式,可以完成出站处理的操作,完成最终的出站处理操作。

1.6. Pipeline模式的优点:

总结一下Pipeline模式的优点,如下:

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

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

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

4、 增加新的请求处理器很方便。

1.7. 小结

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

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

Pipeline模式(netty源码死磕6)的更多相关文章

  1. EventLoop(netty源码死磕4)

    精进篇:netty源码  死磕4-EventLoop的鬼斧神工 目录 1. EventLoop的鬼斧神工 2. 初识 EventLoop 3. Reactor模式回顾 3.1. Reactor模式的组 ...

  2. ChannelHandler揭秘(Netty源码死磕5)

    精进篇:netty源码死磕5  揭开 ChannelHandler 的神秘面纱 目录 1. 前言 2. Handler在经典Reactor中的角色 3. Handler在Netty中的坐标位置 4. ...

  3. JAVA NIO 简介 (netty源码死磕1.1)

    [基础篇]netty 源码死磕1.1:  JAVA NIO简介 1. JAVA NIO简介 Java 中 New I/O类库 是由 Java 1.4 引进的异步 IO.由于之前老的I/O类库是阻塞I/ ...

  4. Java NIO Buffer(netty源码死磕1.2)

    [基础篇]netty源码死磕1.2:  NIO Buffer 1. Java NIO Buffer Buffer是一个抽象类,位于java.nio包中,主要用作缓冲区.Buffer缓冲区本质上是一块可 ...

  5. Netty源码死磕一(netty线程模型及EventLoop机制)

    引言 好久没有写博客了,近期准备把Netty源码啃一遍.在这之前本想直接看源码,但是看到后面发现其实效率不高, 有些概念还是有必要回头再细啃的,特别是其线程模型以及EventLoop的概念. 当然在开 ...

  6. Netty环境搭建 (源码死磕2)

    [正文]netty源码  死磕2: 环境搭建 本小节目录 1. Netty为什么火得屌炸天? 1.1. Netty是什么? 1.2. Netty火到什么程度呢? 1.3. Netty为什么这么火? 2 ...

  7. Pipeline(netty源码)

    精进篇:netty源码死磕6  巧夺天工--Pipeline模式揭秘 1. 巧夺天工--Pipeline模式揭秘 1.1. Pipeline模式简介 管道的发名者叫,Malcolm Douglas M ...

  8. Pipeline inbound(netty源码7)

    netty源码死磕7  Pipeline 入站流程详解 1. Pipeline的入站流程 在讲解入站处理流程前,先脑补和铺垫一下两个知识点: (1)如何向Pipeline添加一个Handler节点 ( ...

  9. Netty 源码(ChannelHandler 死磕)

    精进篇:netty源码死磕5  - 揭开 ChannelHandler 的神秘面纱 目录 1. 前言 2. Handler在经典Reactor中的角色 3. Handler在Netty中的坐标位置 4 ...

随机推荐

  1. 码云的GIT操作

    git操作 git initgit add .git commit -m ""git remote add origin https://git.coding.net/jessei ...

  2. [转载]SecureCRT 绝佳配色方案, 保护你的眼睛

    FROM:http://blog.csdn.net/zklth/article/details/8937905 SecureCRT 绝佳配色方案, 保护你的眼睛   关键词:SecureCRT配色,  ...

  3. POJ 1040 Transportation

    链接:http://poj.org/problem?id=1040 Transportation Time Limit: 1000MS Memory Limit: 10000K Total Submi ...

  4. 系统封装 EasyBoot如何将WIN7安装版提取到光盘

    1 将WIN7光盘中的文件提取到Easyboot根目录,注意不要autorun.inf和setup.exe这两个文件.我们这里的Easyboot已经有了一些其他东西(XP的安装版文件,PE的文件等等, ...

  5. vsftpd 配置:chroot_local_user与chroot_list_enable userlist_enable userlist_deny详解

    默认情况下,如果设置了 userlist_enable=YES,当 userlist_deny 选项设置为 YES 的时候,userlist_file=/etc/vsftpd.userlist 中列出 ...

  6. Laravel请求/Cookies/文件上传

    一.HTTP请求 1.基本示例:通过依赖注入获取当前 HTTP 请求实例,应该在控制器的构造函数或方法中对Illuminate\Http\Request 类进行类型提示,当前请求实例会被服务容器自动注 ...

  7. POJ2536 Gopher II【二分图最大匹配】

    题目链接: http://poj.org/problem? id=2536 题目大意: 有N仅仅鼹鼠和M个洞穴,假设鼹鼠在S秒内不可以跑到洞穴,就会被老鹰捉住吃掉. 鼹鼠跑的速度为V米/秒. 已知一个 ...

  8. 【Excle】科学计数法快速还原

    在Excle的单元格中,如果输入大于11位的数字,结果就会以E+形式显示 如果是单个输入的话,只需要把Excle中的单元格格式设置为文本即可,然后输入就不会出现科学计数法,但是有时候是从外部导入的序号 ...

  9. 定制一个类似地址选择器的view

    代码地址如下:http://www.demodashi.com/demo/12832.html 前言: 这几天也是闲来无事,看看有什么和Scroller相关的控件需要巩固下,原因很简单,前几天看到相关 ...

  10. HTTP协议图解

    1.HTTP简介 http是用于客户端与服务端之间的通信 实际情况中客户端与服务端角色有可能互换,但从一条通信线路来说服务器端和客户端角色是确定的,http协议知道那个是服务端那个是客户端呢. htt ...