「蘑菇街技术」每个人都想听的技术解析--Netty( 五 )

如果按照上面我们分析的数据结构 , 那么按理说最终我们的上述代码会形成如下管道样式 , 那么这时候如果一个读请求进来 , 我们的管道会怎么执行呢?按常理来说 , 既然是双向链表 , 应该是顺序往下执行 , 不断invokeNext就行了吧 。 但是Netty中真是这样嘛?
「蘑菇街技术」每个人都想听的技术解析--Netty文章插图
这里我们直接来看官方给出执行流程图吧 , 在Netty中ChannelHandler根据事件的不同分为InboundHandler和OutboundHandler,前者通常由IO线程触发 , 在Netty触发Inbound事件方法一般以fire开头 , 如Channel注册事件ChannelHandlerContext.fireChannelRegistered() , 而Outbound事件通常为主动发起的网络IO操作 , 如 绑定操作 , ChannelHandlerContext.bind() 。 而如下图 , 我们可知 , 在Netty中 , Outbound事件是自顶向下传播的 , 也就是从Tail节点开始传播 , 而inbound事件则反之 , 自底向上进行传播,也就是从Head节点开始传播 。 所以当一个inbound事件触发时 , 上面的pipeline执行流程应该是 , 1 => 2 =>5 , 反之一个Outbound事件触发时,执行流程应该是 4 => 3
**I/O Request *via {@link Channel} or *{@link ChannelHandlerContext} *| *+---------------------------------------------------+---------------+ *|ChannelPipeline|| *|\|/| *|+---------------------++-----------+----------+| *|| Inbound HandlerN|| Outbound Handler1|| *|+----------+----------++-----------+----------+| *|/|\|| *||\|/| *|+----------+----------++-----------+----------+| *|| Inbound Handler N-1 || Outbound Handler2|| *|+----------+----------++-----------+----------+| *|/|\.| *|..| *| ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()| *|[ method call][method call]| *|..| *|.\|/| *|+----------+----------++-----------+----------+| *|| Inbound Handler2|| Outbound Handler M-1 || *|+----------+----------++-----------+----------+| *|/|\|| *||\|/| *|+----------+----------++-----------+----------+| *|| Inbound Handler1|| Outbound HandlerM|| *|+----------+----------++-----------+----------+| *|/|\|| *+---------------+-----------------------------------+---------------+ *|\|/ *+---------------+-----------------------------------+---------------+ *|||| *|[ Socket.read() ][ Socket.write() ]| *|| *|Netty Internal I/O Threads (Transport Implementation)| *+-------------------------------------------------------------------+ * 这里提一嘴 , 是不是责任链模式都是使用这种双向链表的方式呢?不一定 , 比如在在Tomcat中就不是这样 , 在Tomcat中每一个容器都有一个 Pipeline 对象 , 只要触发这个 Pipeline 的第一个 Valve , 这个容器里 Pipeline 中的 Valve 就都会被调用到 。 但是 , 不同容器的 Pipeline 是怎么链式触发的呢 , 比如 Engine 中 Pipeline 需要调用下层容器 Host 中的 Pipeline 。 而一个容器的Pipeline又怎么调用到下一个容器的Pipeline呢?这是因为 Pipeline 中还有个 getBasic 方法 。 这个 BasicValve 处于 Valve 链表的末端 , 它是 Pipeline 中必不可少的一个 Valve , 负责调用下层容器的 Pipeline 里的第一个 Valve 。 而Wrapper中的最后一个Vavle会创建一个filter链 , 并调用doFilter()方法 , 最后调用到servlet的service方法 , 执行具体的业务处理 。 如下图 ,
「蘑菇街技术」每个人都想听的技术解析--Netty文章插图
(ps:链路的入口在CoyoteAdapter中如下位置)
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);【「蘑菇街技术」每个人都想听的技术解析--Netty】以上是内部关于netty相关的分享 , 大家还想看到哪类文章可以给小编留言哦~