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人脸关键点检测的模 ...
随机推荐
- QComboBox 添加图片(自带addItem函数就有这个功能,从没有注意过)
方法: 使用 QComboxBox::addItem(QIcon, QString); 示例: 点击(此处)折叠或打开 QComboBox *combo_status = new QComboB ...
- java学习之生产者和消费者案例
package com.gh.thread; /** * 生产者和消费者案例 * wait和sleep的区别 * wait不让出监视器锁,sleep让出监视器的锁 * @author ganhang ...
- 【C语言学习】存储类型
C语言中的存储类型主要有四种:auto.static.extern.register ★auto存储类型 默认的存储类型.在C语言中,假设忽略了变量的存储类型,那么编译器就会自己主动默认为auto型 ...
- ThinkPHP - 空模块+空操作
空操作 空操作是指系统在找不到指定的操作方法的时候,会定位到空操作(_empty)方法来执行,利用这个机制,我们可以实现错误页面和一些URL的优化. 例如,下面我们用空操作功能来实现一个城市切换的功能 ...
- UISearchBar去除底部黑线问题
有时我们在设置搜索框的时候底部会出现一条黑线,要 去除这黑线只需设置. [self.searchBar setBackgroundImage:[UIImage new]];
- C#_会员管理系统:开发四(日志查看)
新建一个日志查看窗体: 日志需要的登录时间和登录状态信息由用户刚登录程序时就提供,所以在登录窗体(VIPLogin.cs)中添加代码: //定义一个全局变量 Uid; //用于获取登录成功后的用户名 ...
- 安装uwsgi
apt-get install uwsgi uwsgi-plugin-python
- Uniconnection 连 mysql 有时会断线的
你定义localfailover:=ture.断线后会自己接上 firedac没这种功能.只有unidac有
- 评侯捷的<深入浅出MFC>和李久进的<MFC深入浅出>
侯捷的<深入浅出mfc>相信大家都已经很熟悉了,论坛上也有很多介绍,这里我就不多说了. 而李久进的<mfc深入浅出>,听说的人可能就少得多.原因听说是这本书当时没有怎么宣传,而 ...
- POJ Octal Fractions(JAVA水过)
题目链接:id=1131" target="_blank">CLICK HERE~ 尽管java一下模拟水过,可是我看到别人的一段奇妙代码,贴出和大家共享. imp ...