加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

pipeline

发布时间:2020-12-14 05:06:01 所属栏目:百科 来源:网络整理
导读:三个问题 1.netty是如何判断ChannelHandler类型的? 当调用pipeline添加一个节点时,netty会使用instanceof关键词来判断当前节点是属于inbound类型还是outbound类型,分别用一个boolean类型的变量来标识 2.对于ChannelHandler的添加应该遵循什么样的顺序? I

三个问题

1.netty是如何判断ChannelHandler类型的?

当调用pipeline添加一个节点时,netty会使用instanceof关键词来判断当前节点是属于inbound类型还是outbound类型,分别用一个boolean类型的变量来标识

2.对于ChannelHandler的添加应该遵循什么样的顺序?

Inbound事件类型的传播与添加channelHandler的顺序正相关,outbound事件类型的传播与添加channelHandler的顺序逆相关,

3.用户手动触发事件传播,不同的触发方式有什么样的区别?

(1)在通过channel触发一个事件时,要么从head节点开始传播,这类是inbound事件;要么从tail节点开始传播,这类是outbound事件。

(2)从当前节点触发一个事件时,那么这类事件只会从当前节点开始,如果是inbound类型事件,那么这类事件会从当前节点开始一直传递到最后一个inboundhandler;如果是outbound类型事件,那么这类事件会从当前节点开始向前一直传递到第一个outboundhandler。

pipeline

(1)pipeline的初始化

(2)添加和删除ChannelHandler

(3)事件和异常传播

?

(1)pipeline的初始化

  • pipeline在创建Channel的时候被创建
  • pipeline节点数据结构:ChannelHandlerContext
  • pipeline中的两大哨兵:head和tail

(2)添加和删除ChannelHandler

(a)addLast()方法流程:

  • 判断是否重复添加:如果这个Channel不是@Sharable并且已经被添加过,就拒绝添加
  • 创建节点并添加至链表:创建一个ChannelHandlerContext节点,把ChannelHandler包装进去,最终把这个节点以链表的方式添加到Channel pipeline中
  • 回调添加完成事件:callHandlerAdded0()方法,最典型的事件就是ChannelInitializer,会回调到用户的方法,然后把自身删除

(b)删除ChannelHandler最常见的场景:

  • 权限校验AuthHandler()

(c)删除ChannelHandler流程:

  • 找到节点:getContextOrDie()要么通过Context拿到节点要么抛出异常—>context()通过遍历链表找到ChannelHandler对应的ChannelHandlerContext节点?
  • 链表的删除:remove(),删除的节点不能是head也不能是tail—>remove0(),标准链表的删除过程
  • 回调删除Handler事件:callHandlerRemoved0()方法

(3)事件和异常传播

(a)inBound事件的传播:

  • 何为inBound事件以及ChannnelInboundHandler

  • ChannelRead事件的传播:ABC打印出来也是A—>B—>C

   添加顺序与pipeline中的传播顺序相同

? ? ? ? ? ?channelRead():Head—>A—>B—>C—>Tail

  • SimpleInBoundHandler处理器

(b)outBound事件的传播:

  • 何为outBound事件以及ChannnelOutboundHandler

   outBound事件:用户主动发起的动作,无论读、写、关闭连接? ? ??

  • write()事件的传播:ABC打印出来是C—>B—>A

   添加顺序与pipeline中的传播顺序相反

   write():Tail—>C—>B—>A—>Head

  • ctx.channel().write()和ctx.write()的区别:

   ctx.channel().write()从Tail节点开始传播,ctx.write()从定义它的节点开始传播

(c)异常的传播:

  • 异常的触发链

  (1)异常传播顺序与添加inbound和outbound相同,与分析outbound事件传播顺序相反

  (2)异常传播顺序只与handler的添加顺序相关,与outbound/inbound无关,只要在当前节点出发,最后都会不断地通过next节点触发到下一个节点,如果下一个节点没有做处理,就会继续往下传播

  (3)InBoundA,InBoundB,InBoundC,OutBoundA,OutBoundB,OutBoundC,其中在InBoundB中抛出一个异常 

    异常的触发链:head—> InBoundA—>InBoundB—>InBoundC—>OutBoundA—>OutBoundB—>OutBoundC—>tail

  • 异常处理的最佳实践

    在每一条channel的最后添加一个终极的exception处理器,所有的异常如果在其中没有做处理,最后都会落入这个异常处理器ExceptionCaughtHandler,extends ChannelInboundHandlerAdapter,覆写exceptionCaught方法,针对不同类型的异常分别处理

(4)总结

(a)pipeline的初始化

pipeline在服务端channel和客户端channel被创建的时候创建,创建pipeline的类是服务端channel和客户端channel的公共类AbstractChannel

(b)添加删除ChannelHandler

(1)pipeline中的数据结构是双向链表结构,每一个节点都是channelHandlerContext,channelHandlerContext里面包装了用户自定义的ChannelHandler,添加和删除ChannelHandler最终都是在pipeline的链表结构中添加和删除对应的channelHandlerContext节点

(2)而在添加ChannelHandler的过程中,netty使用instanceof关键字来判断channelHandler的类型,如果该channelHandler实现了channelInboundHandler,那么通过设置一个boolean类型的字段inbound来标识这个handler是inbound类型;同理,如果该channelHandler实现了channelOutboundHandler,那么通过设置一个boolean类型的字段outbound来标识这个handler是outbound类型。

(3)默认情况下pipeline中存在两种类型的节点,一个是Head,一个是Tail,Head节点里面的unsafe负责实现具体协议,而tail节点起到了终止节点和异常传播的作用

(c)事件和异常的传播

(1)pipeline中的传播机制分为3种,其中2种是inbound事件和outbound事件,最后一种是异常事件的传播。

(2)对于inbound事件,默认情况下如果调用channel触发这类事件,触发的规则是从head节点出发不断寻找下一个inboundHandler,最终落到tail节点;如果在当前的channelHandlerContext上触发inbound事件,那么事件只会从当前节点开始向下传播。

(3)对于outbound事件,默认情况下如果调用channel触发这类事件,比如写操作write,触发规则是从tail节点出发不断寻找上一个outboundHandler,最终head节点中的unsafe负责处理真正的写操作;如果在当前的channelHandlerContext上触发outbound事件,那么事件只会从当前节点开始向前传播。

(4)对于异常事件,比如在某个节点上读取数据出错,抛出一个异常,那么异常是直接从当前节点开始往下传播,默认情况下会一直传递到tail节点,tail节点最终会打印出异常信息,那么我们的最佳实践是在pipeline的最后添加一个异常处理器,这个异常处理器可以对不同类型的异常分别做处理。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读