A list of ChannelHandlers which handles or intercepts inbound events and outbound operations of a Channel. ChannelPipeline implements an advanced form of the Intercepting Filter pattern to give a user full control over how an event is handled and how the ChannelHandlers in a pipeline interact with each other.

ChannelPipeline是一个ChannelHandlers的列表, 它用来处理或拦截Channel的进站(inbound)事件或出站(outbound)操作. ChannelPipeline实现了Intercepting Filter 模式, 他使用户可以对事件处理和pipeline中的ChannelHandler之间的交互.

Creation of a pipeline

创建一个管道

Each channel has its own pipeline and it is created automatically when a new channel is created.

每个channel都有自己的pipeline, 并且在channel创建的时候会自动创建一个新的pipeline

How an event flows in a pipeline

管道中的事件是如何流动的

The following diagram describes how I/O events are processed by ChannelHandlers in a ChannelPipeline typically. An I/O event is handled by either a ChannelInboundHandler or a ChannelOutboundHandler and be forwarded to its closest handler by calling the event propagation methods defined in ChannelHandlerContext, such as ChannelHandlerContext.fireChannelRead(Object) and ChannelHandlerContext.write(Object).

下表描述了一个典型的I/O事件在ChannelPipeline中是如何被ChannelHandlers处理的. 一个I/O时间不是被一个ChannelInboundHandler处理就是被一个ChannelOutboundHandler处理, 并且通过调用ChannelHandlerContext中定义的事件传播方法, 它会被转发给它最近的一个handler, 例如ChannelHandlerContext.fireChannelRead(Object) 和 ChannelHandlerContext.write(Object)

附注: 顺序是 request --> Socket.read() --> Inbound Handlers --> Context.wirte() -->  Outbound Handlers --> Socket.write() --> Response

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.

一个 inbound 事件是被 inbound handlers 自底向上处理, 就像上图左边画的那样. 一个 inbound handler 通常是处理图表底部被 I/O 线程生成的入站数据. 入站数据通常是从一个远程端通过真正的input操作读取到的, 例如 SocketChannel.read(ByteBuffer). 如果一个inbound事件流动超过了最顶端的inbound处理器, 他会被丢弃, 或者在需要引起你注意的时候打log

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 Channel. The I/O thread often performs the actual output operation such as SocketChannel.write(ByteBuffer).

一个 outbound 事件是会被 outbound handlers 自顶向下处理的, 就像上图的右边那样. 一个 outbound handler通常生成或转换诸如写请求(write requests)的出站流量.假如一个出站事件流动超出了最底层的outbound处理器, 他将会被一个和Channel相关的I/O线程处理. 这个 I/O 一般表现为真实的输出操作, 例如 SocketChannel.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 with Outbound means it is a outbound handler.

在上面的例子中, 名字以Inbound开始的类表示一个inbound处理器. 名字已Outbound开始的类表示一个outbound处理器

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:

在上面给出的例子中, 在时间进站的时候,handler的计算顺序是 1 2 3 4 5. 当时间出站的时候, 顺序是 5 4 3 2 1. 在此原则之上, ChannelPipeline会跳过某一处理器的计算来缩短栈深:

  • 3 and 4 don't implement ChannelInboundHandler, and therefore the actual evaluation order of an inbound event will be: 1, 2, and 5.
  • 3和4没有实现ChannelInboundHandler, 因此实际的入站事件计算顺序是 1 2 5
  • 1 and 2 don't implement ChannelOutboundHandler, and therefore the actual evaluation order of a outbound event will be: 5, 4, and 3.
  • 1和2没有实现ChannelOutboundHandler, 因此实际的出站事件计算顺序是 5 4 3
  • If 5 implements both ChannelInboundHandler and ChannelOutboundHandler, the evaluation order of an inbound and a outbound event could be 125 and 543 respectively.
  • 假如 5 实现了 ChannelInboundHandler , 又实现了 ChannelOutboundHandler, 那么入站顺序和出站顺序将会是 125 和 543

Forwarding an event to the next handler

将事件转发给下一个处理器

As you might noticed in the diagram shows, a handler has to invoke the event propagation methods in ChannelHandlerContext to forward an event to its next handler. Those methods include:

如你在图表中所见, 一个处理器必须调用ChannelHandlerContext的传播方法来将事件转发给下一个处理器, 这些方法包括:

  • 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 extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("Connected!");
ctx.fireChannelActive();
}
} public class MyOutboundHandler extends ChannelOutboundHandlerAdapter {
@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 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:

一个用户应该在管道中设置一个或多个ChannelHandlers来接收I/O时间(例如read)和请求 I/O 操作(例如write和close).例如, 一个典型的服务器在每个channel的pipeline有如下handlers, 但你的里程可能会根据复杂程度, 协议特征以及业务逻辑有所改变:

1. Protocol Decoder - translates binary data (e.g. ByteBuf) into a Java object.

协议解码器 - 将二进制数据(例如 ByteBuf) 转化为 Java对象


2. Protocol Encoder - translates a Java object into binary data.

协议编码器 - 将Java对象转化为二进制数据


3. Business Logic Handler - performs the actual business logic (e.g. database access).

业务逻辑处理器 - 执行实际业务逻辑(例如数据库访问)


and it could be represented as shown in the following example:

下面是一个代表例子:

static final EventExecutorGroup group = new DefaultEventExecutorGroup(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 a ChannelPipeline 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.

因为一个ChannelPipeline是线程安全的, 所以ChannelHandler可以在任意时间被添加或者删除. 例如, 你可以在需要交换敏感信息的时候插入一个加密处理器, 并在交换完成后移除它.

Netty Associated -- ChannelPipeline的更多相关文章

  1. Netty 源码解析(四): Netty 的 ChannelPipeline

    今天是猿灯塔“365篇原创计划”第四篇. 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty 源码解析(一): 开始 Netty 源码解析(二): Netty 的 Channel Netty ...

  2. Netty 源码解析: Netty 的 ChannelPipeline

    ChannelPipeline和Inbound.Outbound         我想很多读者应该或多或少都有 Netty 中 pipeline 的概念.前面我们说了,使用 Netty 的时候,我们通 ...

  3. Netty源代码学习——ChannelPipeline模型分析

    參考Netty API io.netty.channel.ChannelPipeline A list of ChannelHandlers which handles or intercepts i ...

  4. netty源码解解析(4.0)-8 ChannelPipeline的设计

    io.netty.channel.ChannelPipeline   设计原理 上图中,为了更直观地展示事件处理顺序, 故意有规律地放置两种handler的顺序,实际上ChannelInboundHa ...

  5. 责任链模式的使用-Netty ChannelPipeline和Mina IoFilterChain分析

    本文来自网易云社区 作者:乔安然 1. Chain of Responsiblity 定义: 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链 ...

  6. Netty源码分析之ChannelPipeline(一)—ChannelPipeline的构造与初始化

    Netty中ChannelPipeline实际上类似与一条数据管道,负责传递Channel中读取的消息,它本质上是基于责任链模式的设计与实现,无论是IO事件的拦截器,还是用户自定义的ChannelHa ...

  7. Netty源码分析之ChannelPipeline(二)—ChannelHandler的添加与删除

    上篇文章中,我们对Netty中ChannelPipeline的构造与初始化进行了分析与总结,本篇文章我们将对ChannelHandler的添加与删除操作进行具体的的代码分析: 一.ChannelHan ...

  8. 自顶向下深入分析Netty(七)--ChannelPipeline和ChannelHandler总述

    自顶向下深入分析Netty(七)--ChannelPipeline和ChannelHandler总述 自顶向下深入分析Netty(七)--ChannelPipeline源码实现 自顶向下深入分析Net ...

  9. 谈谈如何使用Netty开发实现高性能的RPC服务器

    RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络,从远程计算机程序上请求服务,而不必了解底层网络技术的协议.说的再直白一点,就是客户端在不必知道 ...

随机推荐

  1. 003.NTP客户端配置

    一 NTP客户端同步方式 ntpdate定时任务同步 ntp服务同步 二 ntpdate定时任务同步 2.1 安装ntp软件 [root@client ~]# yum -y install ntp # ...

  2. [代码审计]云ec电商系统代码审计

    0x00 前言 看了一下博客内最新的文章,竟然是3月28号的,一个多月没写文章了,博客都长草了. 主要是临近毕业,事情繁多,也没有啥时间和心情静下来写.. 不过现在的话,毕业的东西告一段落了,几乎没啥 ...

  3. html (第四本书第1~3章参考)

    前三章都不会的话 呵呵……

  4. 解决apache上访问 cgi脚本时总是在网页中显示出脚本的源代码而不是执行结果的问题

    apache是支持cgi脚本的,但是需要保证四个条件: 1.放置cgi脚本的文件夹本身需要对apache服务器这个用户(一般默认用户名是www,linux下的用户机制请自行百度)开放x(即可执行)权限 ...

  5. bzoj3111: [Zjoi2013]蚂蚁寻路

    题目链接 bzoj3111: [Zjoi2013]蚂蚁寻路 题解 发现走出来的图是一向上的凸起锯齿状 对于每个突出的矩形dp一下就好了 代码 /* */ #include<cstdio> ...

  6. hdu 4451 37届金华赛区 J题

    题意:给出衣服裤子鞋子的数目,有一些衣服和裤子,裤子和鞋子不能搭配,求最终的搭配方案总数 wa点很多,我写wa了很多次,代码能力需要进一步提升 #include<cstdio> #incl ...

  7. 【BZOJ-1913】signaling信号覆盖 极角排序 + 组合

    1913: [Apio2010]signaling 信号覆盖 Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1232  Solved: 506[Subm ...

  8. 一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?

    分为4个步骤: 1)  当发送一个 URL 请求时,不管这个 URL 是 Web 页面的 URL 还是 Web 页面上每个资源的 URL,浏览器都会开启一个线程来处理这个请求,同时在远程 DNS 服务 ...

  9. 并发编程(二):全视角解析volatile

    一.目录 1.引入话题-发散思考 2.volatile深度解析 3.解决volatile原子性问题 4.volatile应用场景 二.引入话题-发散思考 public class T1 { /*vol ...

  10. linux脚本启动停止一个jar

    ###########################启动########################### #!/bin/sh ####定义一个函数在当前文件夹下读取所有jar文件 functi ...