为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
Java

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。

原文出处:https://www.cnblogs.com/brandonli/p/10137555.html

 

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消