精进篇: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的参考代码如下:

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的入站流程和出站流程

转载于:https://blog.51cto.com/14033611/2309994

Pipeline模式(netty源码死磕6)相关推荐

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

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

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

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

  3. Netty 源码(ChannelHandler 死磕)

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

  4. Netty 源码解析系列-服务端启动流程解析

    netty源码解析系列 Netty 源码解析系列-服务端启动流程解析 Netty 源码解析系列-客户端连接接入及读I/O解析 五分钟就能看懂pipeline模型 -Netty 源码解析 1.服务端启动 ...

  5. netty源码学习之服务端客户端初始化

    文章目录 1. AbstractBootstrap类简介 1.1. 核心方法 2. netty服务端创建 2.1. 服务端启动入口 2.2. doBind()方法 2.3. netty服务初始化 2. ...

  6. 【Netty源码分析摘录】(八)新连接的接入

    文章目录 1.问题 2.检测新连接接入 3.创建客户端 channel 4. 绑定 NioEventLoop 4.1 register0 4.1.1 doRegister() 4.1.2 pipeli ...

  7. Netty源码分析第6章(解码器)----第4节: 分隔符解码器

    Netty源码分析第6章(解码器)---->第4节: 分隔符解码器 Netty源码分析第六章: 解码器 第四节: 分隔符解码器 基于分隔符解码器DelimiterBasedFrameDecode ...

  8. Netty源码分析第1章(Netty启动流程)----第4节: 注册多路复用

    Netty源码分析第1章(Netty启动流程)---->第4节: 注册多路复用 Netty源码分析第一章:Netty启动流程   第四节:注册多路复用 回顾下以上的小节, 我们知道了channe ...

  9. Netty源码分析第7章(编码器和写数据)----第2节: MessageToByteEncoder

    Netty源码分析第7章(编码器和写数据)---->第2节: MessageToByteEncoder Netty源码分析第七章: Netty源码分析 第二节: MessageToByteEnc ...

最新文章

  1. 《深入理解mybatis原理》 MyBatis的一级缓存实现详解 及使用注意事项
  2. python3 分离路径 目录 文件名 后缀
  3. linux设置mysql定时任务_原创 Linux下实现Mysql定时任务备份数据
  4. linux http 配置文件,Linux http配置文件解析
  5. 输变电设备物联网节点设备无线组网协议_U-Link 物联网(工业互联网)服务平台
  6. go uint64 转 字符_Go的基本数据类型入门看这一篇就差不多了
  7. 在Visual Studio的Server Explorer中怎样修改表名
  8. beeline执行sql文件_MyBatis的SQL执行流程不清楚?看完这一篇就够了
  9. 多线程003 - 再谈CyclicBarrier
  10. onvif学习笔记1:环境准备
  11. [转]李战大师-悟透delphi 第九章 多层体系结构
  12. python 计算机程序设计-计算机程序设计(Python)
  13. 鼠标经过时改变DIV背景颜色的三种途径
  14. php添加页脚,WordPress网站页脚footer.php修改图文教程
  15. CPU核心数目 与 多线程
  16. 【计算机网络实验】停止等待ARQ算法模拟(Python实现)
  17. 新版标准日本语初级_第三十一课
  18. 【Unity3D】HighlightingSystem3D物体边缘高亮效果使用教程
  19. UE4Lamplight_预结算光照情景
  20. github上操作部署

热门文章

  1. java.lang.Exception: Socket bind failed: [730048]
  2. android 使用Photoshop获取图片某一点的颜色
  3. Android 高级Drawable资源---复合Drawable----状态列表Drawable
  4. 数据库命名规范(转)
  5. PHP基础入门(五)---PHP面向对象实用基础知识
  6. Sublime Text 3 快捷键汇总
  7. 软件工程之四则运算开发感悟与收获
  8. spring入门:beans.xml不提示、别名、创建对象的三种方式
  9. JAAS:灵活的Java安全机制[转]
  10. maven报错找不到依赖