Netty源代码学习——ChannelPipeline模型分析
參考Netty API
A list of ChannelHandlers which handles or intercepts inbound events and outbount operations of aChannel.ChannelPipeline
implements an advanced form of theIntercepting Filter pattern to give a user full control over how an event is handled and how theChannelHandlers
in a pipeline interact with each other.
Creation of a pipeline
Each channel has its own pipeline and it is created automatically when a new channel is created.
How an event flows in a pipeline
The following diagram describes how I/O events are processed by ChannelHandlers in aChannelPipeline typically. An I/O event is handled
by either aChannelInboundHandler or aChannelOutboundHandler and be forwarded to its closest handler by calling the event propagation methods
defined inChannelHandlerContext, such asChannelHandlerContext.fireChannelRead(Object) andChannelHandlerContext.write(Object).
I/O Request
via Channel or
ChannelHandlerContext
|
+---------------------------------------------------+---------------+
| ChannelPipeline | |
| \|/ |
| +---------------------+ +-----------+----------+ |
| | Inbound Handler N | | Outbound Handler 1 | |
| +----------+----------+ +-----------+----------+ |
| /|\ | |
| | \|/ |
| +----------+----------+ +-----------+----------+ |
| | Inbound Handler N-1 | | Outbound Handler 2 | |
| +----------+----------+ +-----------+----------+ |
| /|\ . |
| . . |
| ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
| [ method call] [method call] |
| . . |
| . \|/ |
| +----------+----------+ +-----------+----------+ |
| | Inbound Handler 2 | | Outbound Handler M-1 | |
| +----------+----------+ +-----------+----------+ |
| /|\ | |
| | \|/ |
| +----------+----------+ +-----------+----------+ |
| | Inbound Handler 1 | | Outbound Handler M | |
| +----------+----------+ +-----------+----------+ |
| /|\ | |
+---------------+-----------------------------------+---------------+
| \|/
+---------------+-----------------------------------+---------------+
| | | |
| [ Socket.read() ] [ Socket.write() ] |
| |
| Netty Internal I/O Threads (Transport Implementation) |
+-------------------------------------------------------------------+
Figure 1
An inbound event is handled by the inbound handlers in the bottom-up direction as shown on the left side of the diagram. An inbound handler usually handles the inbound data generated by the I/O thread on the bottom of the diagram. The inbound data is often
read from a remote peer via the actual input operation such as SocketChannel.read(ByteBuffer). If an inbound event goes beyond the top inbound handler, it is discarded silently, or logged if it needs
your attention.
An outbound event is handled by the outbound handler in the top-down direction as shown on the right side of the diagram. An outbound handler usually generates or transforms the outbound traffic such as write requests. If an outbound event goes beyond the
bottom outbound handler, it is handled by an I/O thread associated with the . The I/O thread often performs the actual output operation such as
ChannelSocketChannel.write(ByteBuffer).
For example, let us assume that we created the following pipeline:
ChannelPipelinep = ...;
p.addLast("1", new InboundHandlerA());
p.addLast("2", new InboundHandlerB());
p.addLast("3", new OutboundHandlerA());
p.addLast("4", new OutboundHandlerB());
p.addLast("5", new InboundOutboundHandlerX());
In the example above, the class whose name starts with Inbound means it is an inbound handler. The class whose name starts withOutbound means it is a outbound handler.
In the given example configuration, the handler evaluation order is 1, 2, 3, 4, 5 when an event goes inbound. When an event goes outbound, the order is 5, 4, 3, 2, 1. On top of this principle,ChannelPipeline
skips the evaluation of certain handlers to shorten the stack depth:
- 3 and 4 don't implement
ChannelInboundHandler, and therefore the actual evaluation order of an inbound event will be: 1, 2, and 5. - 1 and 2 implement
ChannelOutboundHandler, and therefore the actual evaluation order of a outbound event will be: 5, 4, and 3. - If 5 implements both
ChannelInboundHandlerandChannelOutboundHandler, the evaluation order of an inbound and a outbound event could be
125 and 543 respectively.
Forwarding an event to the next handler
As you might noticed in the diagram shows, a handler has to invoke the event propagation methods inChannelHandlerContext to forward an event to its next handler. Those methods include:
- Inbound event propagation methods:
ChannelHandlerContext.fireChannelRegistered()ChannelHandlerContext.fireChannelActive()ChannelHandlerContext.fireChannelRead(Object)ChannelHandlerContext.fireChannelReadComplete()ChannelHandlerContext.fireExceptionCaught(Throwable)ChannelHandlerContext.fireUserEventTriggered(Object)ChannelHandlerContext.fireChannelWritabilityChanged()ChannelHandlerContext.fireChannelInactive()ChannelHandlerContext.fireChannelUnregistered()
- Outbound event propagation methods:
ChannelHandlerContext.bind(SocketAddress, ChannelPromise)ChannelHandlerContext.connect(SocketAddress, SocketAddress, ChannelPromise)ChannelHandlerContext.write(Object, ChannelPromise)ChannelHandlerContext.flush()ChannelHandlerContext.read()ChannelHandlerContext.disconnect(ChannelPromise)ChannelHandlerContext.close(ChannelPromise)ChannelHandlerContext.deregister(ChannelPromise)
and the following example shows how the event propagation is usually done:
public class MyInboundHandler extendsChannelInboundHandlerAdapter{
@Override
public void channelActive(ChannelHandlerContextctx) {
System.out.println("Connected!");
ctx.fireChannelActive();
}
} public clas MyOutboundHandler extendsChannelOutboundHandlerAdapter{
@Override
public void close(ChannelHandlerContextctx,ChannelPromisepromise) {
System.out.println("Closing ..");
ctx.close(promise);
}
}
Building a pipeline
A user is supposed to have one or more ChannelHandlers in a pipeline to receive I/O events (e.g. read) and to request I/O operations (e.g. write and close). For example, a typical server will have
the following handlers in each channel's pipeline, but your mileage may vary depending on the complexity and characteristics of the protocol and business logic:
- Protocol Decoder - translates binary data (e.g.
ByteBuf) into a Java object. - Protocol Encoder - translates a Java object into binary data.
- Business Logic Handler - performs the actual business logic (e.g. database access).
and it could be represented as shown in the following example:
static finalEventExecutorGroupgroup = newDefaultEventExecutorGroup(16);
...ChannelPipelinepipeline = ch.pipeline(); pipeline.addLast("decoder", new MyProtocolDecoder());
pipeline.addLast("encoder", new MyProtocolEncoder()); // Tell the pipeline to run MyBusinessLogicHandler's event handler methods
// in a different thread than an I/O thread so that the I/O thread is not blocked by
// a time-consuming task.
// If your business logic is fully asynchronous or finished very quickly, you don't
// need to specify a group.
pipeline.addLast(group, "handler", new MyBusinessLogicHandler());
Thread safety
A ChannelHandler can be added or removed at any time because aChannelPipeline is thread safe. For example, you can insert an encryption
handler when sensitive information is about to be exchanged, and remove it after the exchange.
—————>>>>>>>>>>>>>>>>>>华丽的分界线<<<<<<<<<<<<<<<<<—————————————
Figure1 变形:
+-------------------------------------------------------------------+
| IN |
| | |
| | |
| [(Socket)read] |
| | |
| | |
| \|/ |
| +----------+----------+ |
| | Inbound Handler 1 | |
| +----------+----------+ |
| | |
| \|/ |
| +----------+----------+ |
| | Inbound Handler 2 | |
| +----------+----------+ |
| . |
| . |
| \./ |
| ChannelHandlerContext.FireIN_EVT |
| [ method call] |
| . |
| . |
| \./ |
| +----------+----------+ |
| | Inbound Handler N-1 | |
| +----------+----------+ |
| \|/ |
| | |
| +----------+----------+ |
| | Inbound Handler N | |
| +----------+----------+ |
| | |
| \|/ |
| | |
+---------------------------------+---------------------------------+
| | |
| | |
| Application |
| | |
| | |
+---------------------------------+---------------------------------+
| | |
| \|/ |
| +-----------+----------+ |
| | Outbound Handler 1 | |
| +-----------+----------+ |
| | |
| \|/
| +-----------+----------+ |
| | Outbound Handler 2 | |
| +-----------+----------+ |
| . |
| . |
| \./ |
| ChannelHandlerContext.OUT_EVT() |
| [ method call] |
| . |
| . |
| \./ |
| +-----------+----------+ |
| | Outbound Handler M-1 | |
| +-----------+----------+ |
| | |
| \|/ |
| +-----------+----------+ |
| | Outbound Handler M | |
| +-----------+----------+ |
| | |
| \|/ |
| [(Socket)write] |
| | |
| | |
| \|/ |
| | |
| OUT |
+---------------+-----------------------------------+---------------+
责任链模式:
在阎宏博士的《JAVA与模式》一书中开头是这样描写叙述责任链(Chain of Responsibility)模式的:
责任链模式是一种对象的行为模式。在责任链模式里,非常多对象由每个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的client并不知道链上的哪一个对象终于处理这个请求,这使得系统能够在不影响client的情况下动态地又一次组织和分配责任。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd29ya2luZ19icmFpbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
责任链模式涉及到的角色例如以下所看到的:
● 抽象处理者(Handler)角色:定义出一个处理请求的接口。假设须要,接口能够定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。
上图中Handler类的聚合关系给出了详细子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
● 详细处理者(ConcreteHandler)角色:详细处理者接到请求后。能够选择将请求处理掉,或者将请求传给下家。
因为详细处理者持有对下家的引用,因此,假设须要,详细处理者能够訪问下家。
Java website development中的filter也是责任链模式。
參考文章:http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html。
Netty源代码学习——ChannelPipeline模型分析的更多相关文章
- Netty源代码学习——EventLoopGroup原理:NioEventLoopGroup分析
类结构图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd29ya2luZ19icmFpbg==/font/5a6L5L2T/fontsize/400/f ...
- Netty源代码学习——Included transports(变速箱)
Transport API核心: Channel介面 类图表示Channel含有Pipeline和Config接口,pipeline上一节有所介绍. Channel是线程安全的,这表示在多线环境下操作 ...
- Netty 源码学习——客户端流程分析
Netty 源码学习--客户端流程分析 友情提醒: 需要观看者具备一些 NIO 的知识,否则看起来有的地方可能会不明白. 使用版本依赖 <dependency> <groupId&g ...
- Netty中的ChannelPipeline源码分析
ChannelPipeline在Netty中是用来处理请求的责任链,默认实现是DefaultChannelPipeline,其构造方法如下: private final Channel channel ...
- ROS_Kinetic_29 kamtoa simulation学习与示例分析(一)
致谢源代码网址:https://github.com/Tutorgaming/kamtoa-simulation kamtoa simulation学习与示例分析(一) 源码学习与分析是学习ROS,包 ...
- 《精通并发与Netty》学习笔记(01 - netty介绍及环境搭建)
一.Netty介绍 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. ...
- struts2源代码学习之初始化(一)
看struts2源代码已有一段时日,从今天開始,就做一个总结吧. 首先,先看看怎么调试struts2源代码吧,主要是下面步骤: 使用Myeclipse创建一个webproject 导入struts2须 ...
- 读Flask源代码学习Python--config原理
读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因 莫名其妙在第一份工作中使用了从来没有接 ...
- dlib人脸关键点检测的模型分析与压缩
本文系原创,转载请注明出处~ 小喵的博客:https://www.miaoerduo.com 博客原文(排版更精美):https://www.miaoerduo.com/c/dlib人脸关键点检测的模 ...
随机推荐
- hibernate 缓存 4.3
缓存在hibernate中是天生就有的,是一级缓存,当session关闭时一级缓存就失效了 一级缓存是内置的,生效范围是在同一个session中才行.二级缓存是需要配置才有 判断当前项在不在一级缓存中 ...
- C# 计算器 运算符和数字键的keys对照
keys. private void Computer_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.NumPad0) ...
- poj 3984 迷宫问题(dfs)
题目链接:http://poj.org/problem?id=3984 思路:经典型的DFS题目.搜索时注意剪枝:越界处理,不能访问处理. 代码: #include <iostream> ...
- JAE京东云引擎Git上传管理代码教程和京东云数据库导入导出管理
文章目录 Git管理准备工作 Git工具上传代码 发布代码装程序 mywebsql管理 京东云引擎小结 JAE京东云引擎是京东推出的支持Java.Ruby.Python.PHP.Node.js多语 ...
- Boost.Asio基础(三)
Socket控制 以下的函数进行处理一些高级的socket选项: get_io_service():返回io_service实例 get_option(option):返回socket option对 ...
- Centos6.4下tar包安装最新版Mysql5.6
1.下载 mysql:http://www.mysql.com/downloads/ (须要注冊ORACLE账号) 版本号:mysql-advanced-5.6.21-linux-glibc2.5-x ...
- cacti气象图调整(批量位置调整、更改生成图大小等)
cacti气象图能够非常直观的看到各个节点的流量.这里用的是CactiEZ中文版 V10 1.调整气象图大小 默认有一个1024像素的背景图可选, 这里我们须要新增一个1600像素的背景图. 背景图自 ...
- TCP/IP之TCP连接的建立与中止状态分析
TCP连接的建立可以简单的称为三次握手,而连接的中止则可以叫做四次握手. 1.连接的建立: c端发起请求同步(用SYN段等于1的TCP报文),确认某个端口是否监听: s端应答(用ACK段等于1的TCP ...
- 静态化 - 伪静态技术(Apache Rewrite 实现)
打开apache的配置文件httpd.conf 找到 #LoadModule rewrite_module modules/mod_rewrite.so 把前面#去掉.没有则添加,但必选独占一行,使a ...
- 设计模式 ( 十五 ) 中介者模式Mediator(对象行为型)
设计模式 ( 十五 ) 中介者模式Mediator(对象行为型) 1.概述 在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责,即将行为分布到各 ...