Netty源代码学习——ChannelPipeline模型分析
參考Netty API
A list of ChannelHandler
s 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 theChannelHandler
s
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 ChannelHandler
s 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:
ChannelPipeline
p = ...;
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
ChannelInboundHandler
andChannelOutboundHandler
, 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(ChannelHandlerContext
ctx) {
System.out.println("Connected!");
ctx.fireChannelActive();
}
} public clas MyOutboundHandler extendsChannelOutboundHandlerAdapter
{
@Override
public void close(ChannelHandlerContext
ctx,ChannelPromise
promise) {
System.out.println("Closing ..");
ctx.close(promise);
}
}
Building a pipeline
A user is supposed to have one or more ChannelHandler
s 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 finalEventExecutorGroup
group = newDefaultEventExecutorGroup
(16);
...ChannelPipeline
pipeline = 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人脸关键点检测的模 ...
随机推荐
- VS2010/MFC对话框一:创建对话框模板和修改对话框属性
创建对话框主要分两大步: 第一,创建对话框资源,主要包括创建新的对话框模板.设置对话框属性和为对话框添加各种控件: 第二,生成对话框类,主要包括新建对话框类.添加控件变量和控件的消息处理函数等. 创建 ...
- Activity 的生命周期
两个大窗口的Activity之间的切换: 启动一个新的Activity时,需要依次调用oncreate.onstart.onResume方法,OnCreate方法是在第一次创建Activity的时候调 ...
- linux grep详解
Table of Contents 1. grep简介 2. grep正则表达式元字符集(基本集) 3. 用于egrep和 grep -E的元字符扩展集 4. POSIX字符类 5. Grep命令选项 ...
- HDU 5045 Contest(状压DP)
Problem Description In the ACM International Collegiate Programming Contest, each team consist of th ...
- [POJ 2588]--Snakes(并查集)
题目链接:http://poj.org/problem?id=2588 Snakes Time Limit: 1000MS Memory Limit: 65536K Description B ...
- 开源网络库的分析libev libevent nginx ....
最经看关于网络编程的一些书,对于网络编程中的一些基本东西,开源库已经封装的很好了,但是库归根结底还是使用的基本API,所以就想着分析一下,尤其是在看了各个库的介绍以后,所以这段时间想在这个方向投入一点 ...
- Hbase 配置问题(ERROR: org.apache.hadoop.hbase.PleaseHoldException: org.apache.hadoop.hbase.PleaseHoldEx)
ERROR: org.apache.hadoop.hbase.PleaseHoldException: org.apache.hadoop.hbase.PleaseHoldException: Mas ...
- JMS 企业开发流程实现
关于JMS的一些介绍参见[http://blog.csdn.net/aking21alinjuju/article/details/6051421] [补充] 消息的组成 1. 头(head) 每条J ...
- USACO Healthy Holsteins DFS
使用排列组合,遍历所有可能的情况C(1)+C(2)+C(3)……C(n)= 2^G种组合 数据规模不大,暴力过去最多也就是2^15 = 23768种情况 所以就暴力咯,不过还是Debug了一会 Sou ...
- Chapter 11 迪米特法则
迪米特法则也叫最少知识原则:如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用.如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用. 迪米特法则首先强调的前提是 ...