io.netty.channel.ChannelPipeline
 
设计原理

  

  上图中,为了更直观地展示事件处理顺序, 故意有规律地放置两种handler的顺序,实际上ChannelInboundHandler和ChanneOutboundHandler的顺序可以是任意,取决于用户调用add方法把handler方在哪里。
 
  ChannelPipeline的特性:
  1. 它是一个双向链表
  2. 每个节点持有一个ChannelHandler实例,这个实例可以是ChannelInboundHandler类型或ChannelOutboundHandler类型,
  3. ChannelInboundHandler类型的handler只处理inbound事件,ChannelInboundHandler只处理outbound事件。
  4. inbound事件处理顺序是由链表头到链表尾,outbound事件的处理顺序是由链表尾到链表头。
  5. inbound事件由netty内部触发,最终由netty外部的代码消费。outbound事件由netty外部的代码触发,最终由netty内部消费。
 
接口设计
  ChannelPipeline接口定义的方法分为三种类型:链表管理的方法、触发outbound事件的方法、触发inbound事件的方法。
 
链表管理的方法
添加:addFirst, addLast, addAfter, addBefore。
删除:removeFirst, removeLast, remove。
替换:replace。
查找:first, last, get。
 
触发outbound事件的方法
bind(SocketAddress, ChannelPromise)
connect(SocketAddress, SocketAddress, ChannelPromise)
write(Object, ChannelPromise)
flush()
read()
disconnect(ChannelPromise)
close(ChannelPromise)
deregister(ChannelPromise)
 
触发inbound事件的方法
fireChannelRegistered()
fireChannelActive()
fireChannelRead(Object)
fireChannelReadComplete()
fireExceptionCaught(Throwable)
fireUserEventTriggered(Object)
fireChannelWritabilityChanged()
fireChannelInactive()
fireChannelUnregistered()
 
 
 
Channel,EventLoop,ChannelPipeline,EventExecutor和ChannelHandler之间的关系
  每个channel持有一个eventLoop, channel.unsafe的方法会在这个eventLoop中执行。那么问题来了,使用add方法向channelPiple中添加一个channelHandler,这个handler的方法在哪里执行呢?下面以addLast为例看看添加方法。
ChannelPipeline addLast(ChannelHandler... handlers)
ChannelPipeline addLast(EventExecutorGroup group, ChannelHandler... handlers)
ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler)
 
  channelPiple负责为每个新添加的handler分配一个eventExecutor。如果你调用了带grop参数的方法添加handler ,channelPiple会从group中取出一个eventExecutor分配给这个handler, 这时handler中的回调方法会在这个eventExecutor线程中执行,否则channelPiple会把channel的eventLoop当成eventExecutor分配给这个handler,这时这个handler的回调方法会在eventLoop的线程中执行。这个两者有什么不同呢?如果没你没有给handler指定group,它将会和channel的I/O操作共享线程资源,它能得到多少线程资源取决于eventLoop的ioRatio属性的设置,执行时间过长的handler的回调方法会影响I/O操作。如果指定了group,handler的回调方法和channel的I/O操作将会被隔离到不同的线程中。在高并发情况下,强烈建议为不同功能的handler指定不同的group。
每个channel实例在创建的时候,它自己负责创建一个channelPiple实例。随后这个channel会被注册到一个eventLoop中,eventLoop负责处理channel上触发的I/O事件,把I/O事件转换成对channel.unsafe方法的调用。unsafe负责做实际的I/O操作,根据需要调用channelPiple触发事件。channelPiple依次调用合适的handler处理事件。这里的"依次”和“合适”的含义是:
  • 如果是inbound事件,会从头到尾按顺序调用双向链表上的ChannelInboundHandler类型的handler。
  • 如果是outbound事件,会从尾到头按顺序调用双向链表上的ChannelOutboundHandler类型的handler。
  piplePile确保一个handler调用始终在一个唯一的eventExecutor中,这个eventExecutor可能是channel的eventLoop,也可能是从用户指定的eventExecutorGroup中分配到的一个executor。

netty源码解解析(4.0)-8 ChannelPipeline的设计的更多相关文章

  1. netty源码解解析(4.0)-10 ChannelPipleline的默认实现--事件传递及处理

    事件触发.传递.处理是DefaultChannelPipleline实现的另一个核心能力.在前面在章节中粗略地讲过了事件的处理流程,本章将会详细地分析其中的所有关键细节.这些关键点包括: 事件触发接口 ...

  2. netty源码解解析(4.0)-11 Channel NIO实现-概览

      结构设计 Channel的NIO实现位于io.netty.channel.nio包和io.netty.channel.socket.nio包中,其中io.netty.channel.nio是抽象实 ...

  3. netty源码解解析(4.0)-17 ChannelHandler: IdleStateHandler实现

    io.netty.handler.timeout.IdleStateHandler功能是监测Channel上read, write或者这两者的空闲状态.当Channel超过了指定的空闲时间时,这个Ha ...

  4. netty源码解解析(4.0)-18 ChannelHandler: codec--编解码框架

    编解码框架和一些常用的实现位于io.netty.handler.codec包中. 编解码框架包含两部分:Byte流和特定类型数据之间的编解码,也叫序列化和反序列化.不类型数据之间的转换. 下图是编解码 ...

  5. netty源码解解析(4.0)-20 ChannelHandler: 自己实现一个自定义协议的服务器和客户端

    本章不会直接分析Netty源码,而是通过使用Netty的能力实现一个自定义协议的服务器和客户端.通过这样的实践,可以更深刻地理解Netty的相关代码,同时可以了解,在设计实现自定义协议的过程中需要解决 ...

  6. netty源码解解析(4.0)-15 Channel NIO实现:写数据

    写数据是NIO Channel实现的另一个比较复杂的功能.每一个channel都有一个outboundBuffer,这是一个输出缓冲区.当调用channel的write方法写数据时,这个数据被一系列C ...

  7. netty源码解解析(4.0)-14 Channel NIO实现:读取数据

     本章分析Nio Channel的数据读取功能的实现. Channel读取数据需要Channel和ChannelHandler配合使用,netty设计数据读取功能包括三个要素:Channel, Eve ...

  8. netty源码解解析(4.0)-4 线程模型-概览

    netty线程体系概览 netty的高并发能力很大程度上由它的线程模型决定的,netty定义了两种类型的线程: I/O线程: EventLoop, EventLoopGroup.一个EventLoop ...

  9. netty源码解解析(4.0)-12 Channel NIO实现:channel初始化

    创建一个channel实例,并把它register到eventLoopGroup中之后,这个channel然后处于inactive状态,仍然是不可用的.只有在bind或connect方法调用成功之后才 ...

随机推荐

  1. Javascript上传超大文件实例

    因业务需求需要向伺服器上传大于1GB以上的视频文件,其实网上也能找到很多大文件上传的第三方组件,问题是要么用起来相当不方便,总出现一些bug,要么收费太贵(费用几千,甚至还限定使用数量),最终自己开发 ...

  2. 用Django ORM实现树状结构

    前言 之前看对于用关系数据库实现树状结构的方法就知道一直做自关联的表,但是感觉自关联查询太慢了,最近看到一篇文章,感觉视野开拓了好多,文章:数据库表设计,没有最好只有最适合来自:微信. 下面就针对这里 ...

  3. AJAX笔记整理

    AJAX: Asynchronous JavaScript and XML,异步的Javascirpt和Xml. Asynchronous:异步 与之对应的是 synchronous:同步,我们要知道 ...

  4. 关于esp32的ADC采集

    对于ADC采集 程序源码如下: /* ADC1 Example This example code is in the Public Domain (or CC0 licensed, at your ...

  5. [ 10.03 ]CF每日一题系列—— 534B贪心

    Descripe: 贪心,贪在哪里呢…… 给你初始速度,结尾速度,行驶秒数,每秒速度可变化的范围,问你行驶秒数内最远可以行驶多少距离 Solution: 贪心,我是否加速,就是看剩下的时间能不能减到原 ...

  6. Nginx 教程

    开源版:http://nginx.org 商业版:http://nginx.com 阿里Tengine OpenResty开源版.商业版 视频教程:哔哩哔哩 菜鸟教程:nginx安装 1.初识 Nig ...

  7. [数据清洗]-Pandas 清洗“脏”数据(一)

    概要 准备工作 检查数据 处理缺失数据 添加默认值 删除不完整的行 删除不完整的列 规范化数据类型 必要的转换 重命名列名 保存结果 更多资源 Pandas 是 Python 中很流行的类库,使用它可 ...

  8. Vue学习笔记八:v-for,v-if,v-show指令

    目录 v-for指令:遍历 HTML和效果图 v-for讲解 v-if和v-show:创建,删除,显示,隐藏 HTML和效果图 v-if和v-show的原理 v-for指令:遍历 HTML和效果图 有 ...

  9. 833. Find And Replace in String

    To some string S, we will perform some replacement operations that replace groups of letters with ne ...

  10. 1.html基础标签:文本+链接+图片

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...