您的位置:首页 > 其它

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

2018-12-24 23:43 846 查看
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。

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: