zoukankan      html  css  js  c++  java
  • netty源码解析(4.0)-8 ChannelPipeline的设计

    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。

     

  • 相关阅读:
    Java面试:用set集合的时候,重写过hashcode()和equal()方法吗?有什么作用?
    Bootstrap起步
    Java NIO
    Dobbo和SpringCloud区别
    Java虚拟机类加载机制和双亲委派模型
    继承和组合的特点和区别
    LinkedList和ArrayList底层原理
    聚集索引和非聚集索引
    Stream和迭代器的区别
    悲观锁和乐观锁
  • 原文地址:https://www.cnblogs.com/brandonli/p/10137555.html
Copyright © 2011-2022 走看看