• 流水线 Pipeline 机制梳理


    来梳理一下Netty的反应器模式中各个组件之间的关系:

    (1)反应器(或者SubReactor子反应器)和通道之间是一对多的关系:一个反应器可以查询很多个通道的IO事件。
    (2)通道和Handler处理器实例之间,是多对多的关系:一个通道的IO事件被多个的Handler实例处理;一个Handler处理器实例也能绑定到很多的通道,处理多个通道的IO事件。
    问题是:通道和Handler处理器实例之间的绑定关系,Netty是如何组织的呢? Netty设计了一个特殊的组件,叫作ChannelPipeline(通道流水线),它像一条 管道,将绑定到一个通道的多个Handler处理器实例,串在一起,形成一条流水线。 ChannelPipeline(通道流水线)的默认实现,实际上被设计成一个双向链表。所有 的Handler处理器实例被包装成了双向链表的节点,被加入到了ChannelPipeline(通 道流水线)中能够支持动态地添加和删除Handler业务处理器。重点申明:一个Netty通道拥有一条Handler处理器流水线,成员的名称叫作pipeline。
    问题来了:这里为什么将pipeline翻译成流水线,而不是翻译成为管道呢?这是有原因的。具体来说,与流水线内部的Handler处理器之间处理IO事件的先后次序有关。
    以入站处理为例。每一个来自通道的IO事件,都会进入一次ChannelPipeline通 道流水线。在进入第一个Handler处理器后,这个IO事件将按照既定的从前往后次 序,在流水线上不断地向后流动,流向下一个Handler处理器
    在向后流动的过程中,会出现3种情况:
    (1)如果后面还有其他Handler入站处理器,那么IO事件可以交给下一个Handler处理器,向后流动。
    (2)如果后面没有其他的入站处理器,这就意味着这个IO事件在此次流水线中的处理结束了。
    (3)如果在流水线中间需要终止流动,可以选择不将IO事件交给下一个Handler处理器,流水线的执行也被终止了。
    为什么说Handler的处理是按照既定的次序,而不是从前到后的次序呢? Netty是这样规定的:入站处理器Handler的执行次序,是从前到后出站处理器Handler的执 行次序,是从后到前。总之,IO事件在流水线上的执行次序,与IO事件的类型是有关系的,如图6-6所示
    除了流动的方向与IO操作的类型有关之外,流动过程中经过的处理器节点的类型,也是与IO操作的类型有关。入站的IO操作只会且只能从Inbound入站处理器类型的Handler流过;出站的IO操作只会且只能从Outbound出站处理器类型的Handler流过。
    (1)底层的SocketChannel read()方法读取 ByteBuf,触发ChannelRead事件,由IO线程NioEventLoop调用ChannelPipeline的fireChannelRead(Object msg)方法,将消息(ByteBuf)传到ChannelPipeline。
    (2)消息依次被HeadContext、ChannelHandler1、ChannelHandler2……TailHandler拦截和处理,在这个过程中,任何ChannelHandler都可以中断当前的流程,结束消息的传递。
    (3)调用ChannelHandlerContext的 write()方法发送消息,消息从TailContext开始,途经ChannelHandlerN……ChannelHandlerl、HeadHandler,最终被添加到消息发送缓冲区等待刷新和发送,在此过程中也可以中断消息的传递,例如当编码失败时,程,构造异常的Future返回。
    总结:read()读取的消息会从读取缓冲区第一个handler流到最后一个handler,write()写回的消息会从最后一个handler流到第一个handler最后到发送缓冲区。

    【ChannelHandler工作机制】

    Netty 的ChannelHandler工作原理与Servlet Filter机制一致,它将Channel的数据管道抽象为ChannelPipeline,消息在ChannelPipeline中流动和传递。ChannelPipeline持有I/O事件拦截器ChannelHandler的链表,由ChannelHandler对I/O事件进行拦截和处理, 可以方便地通过新增和删除ChannelHandler来实现不同的业务逻辑定制,不需要对已有的 ChannelHandler进行修改,能够实现对修改封闭和对扩展的支持。对于用户来说,基于Netty的编程就是开发和组装各种系统与业务ChannelHandler,实现业务逻辑处理。
    ChannelPipeline是ChannelHandler的编排管理容器,它内部维护了一个ChannelHandler的链表和迭代器,可以方便地实现ChannelHandler的查找、添加、替换和删除。
    在实际业务场景中,ChannelPipeline通常需要添加如下几类ChannelHandler。对于耗时的业务逻辑执行,例如访问数据库、中间件、第三方系统等,则需要切换到业务线程池中,避免阻塞Netty的 NioEventLoop线程,导致消息无法接收和发送。
    (1)协议解码ChannelHandler。
    (2)协议编码ChannelHandler。
    (3)业务逻辑执行ChannelHandler。
  • 相关阅读:
    LeetCode50天刷题计划(Day 9—— 整数转罗马数字(20.40-22.10)
    如何翻译文档?不妨试试这些软件
    【QML】QML控件组件
    5年没发paper,学术论文写到头秃...
    网络中的一些概念
    终日乾乾,夕惕若厉
    集成学习方法之随机森林-入门
    vue3使用Element ui plus中MessageBox消息框+radio框配合使用
    推荐系统最通俗介绍
    2—C++程序设计:C++简单程序设计
  • 原文地址:https://blog.csdn.net/qq_34448345/article/details/127440194