前段时间在B站学习Netty,讲到出站入站的机制时一直没搞明白到底是怎么弄的,直到开始讲源码部分时才终于搞明白。

先来看看Netty官方有关出站入站机制的解释:

按照图片的理解,则是在通道中,每次出现读事件时,会从头至尾依次调用Inbound即入站方法处理;
而触发写事件时,则会从尾到头依次调用outbound即出站方法处理。

这里会给人一种错觉,那就是netty在内部维护了两个单向链表实现出站入站操作,而事实上,ChannelPipeline中实际上是维护了一条由ChannelHandlerContext组成的双向链表,这里我们后面再说。

我们先来看一个例子,模拟一个场景,客户端向服务器发送数据,服务器写回客户端一个响应数据:
整体流程如图:

下面进行每一步的讲解:

  1. 首先服务器接收到来自客户端的数据,通过read方法获取,此时数据是存储在ByteBuf中
  2. 读取后的下一步首先要解码(入站)获取其真实数据,并且我们在解码器中定义了一个方法,将数据写回
  3. 执行写回操作之前,首先会调用Encoder(出站)进行编码,最后才将数据写回给客户端

以上体现了出站和入站的基本思想,即:
1. 入站操作主要是指读取数据的操作;而出站操作主要是指写入数据的操作
2. 入站会从先读取,再执行入站的Handler;出站会先执行出站的Handler,再写入

到这里其实出入站的操作已经解释完毕,但是底层的问题还没有解决:为什么只用了一个双向链表就可以实现?

还是看源码,首先是ChannelPipeline的默认实现类:

public class DefaultChannelPipeline implements ChannelPipeline {final AbstractChannelHandlerContext head;final AbstractChannelHandlerContext tail;/*省略*/
}

这里只保留了核心的部分,可以看到,它的首尾结点是由AbstractChannelHandlerContext 组成的,我们继续点开:

abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {volatile AbstractChannelHandlerContext next;volatile AbstractChannelHandlerContext prev;
}

这里应该看得比较明白了,它拥有next指向下一个结点,也有prev指向前一个结点。
这里先提一点,handler的事件处理是通过fireChannelxxx完成的。

我们在AbstractChannelHandlerContext中找到如下方法:

private AbstractChannelHandlerContext findContextInbound(int mask) {AbstractChannelHandlerContext ctx = this;EventExecutor currentExecutor = executor();do {ctx = ctx.next;} while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_INBOUND));return ctx;
}private AbstractChannelHandlerContext findContextOutbound(int mask) {AbstractChannelHandlerContext ctx = this;EventExecutor currentExecutor = executor();do {ctx = ctx.prev;} while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_OUTBOUND));return ctx;
}

相信对于有经验的程序员来说到这里就已经明白了netty是怎么实现的了。
虽然看起来像是用了两个链表,其实是通过遍历同一个双向链表来实现入站和出站操作的。

  1. 当操作为读时,会调用findContextInbound(int mask)方法,从头至尾遍历InboundHandler,注意,只遍历Inbound操作;
  2. 而当操作为写时,会调用findContextOutbound(int mask),从尾到头遍历OutboundHandler,这时只有OutBound操作被执行

以上就是我对于Netty出站、入站的理解。

Netty 出站入站机制详解相关推荐

  1. netty的零拷贝、架构设计、ByteBuf扩容机制详解

    文章目录 1. netty高并发架构设计精髓 ①:主从.Reactor线程模型 ②:NIO多路复用非阻塞 ③:无锁串行化设计思想 ④:高可用.可扩展架构 ⑤:直接内存和零拷贝 ⑥:ByteBuf内存池 ...

  2. 顺序栈基本操作(入栈和出栈)C语言详解

    #include <stdio.h> #include <stdlib.h> /*顺序栈基本操作(入栈和出栈)C语言详解栈的具体实现(1)顺序栈(2)链栈栈的应用(1)回退 ( ...

  3. fgo服务器维护后抽奖,fgo:抽卡机制详解 彩圈是必定会出五星的

    原标题:fgo:抽卡机制详解 彩圈是必定会出五星的 介于春节期间,不少玩家手头都很富裕,所以对于fgo的卡池方面的投入也是非常多的,而一个很现实与实际的问题就摆在了不少玩家面前,fgo的游戏抽卡机制到 ...

  4. Android学习笔记——Android 签名机制详解

    Android 签名机制详解 近期由于工作需要在学习 Android 的签名机制,因为没有现成资料,只能通过开发者文档和阅读博客的方式对 Android 签名机制进行大致了解.过程中查阅到的资料相对零 ...

  5. Binder机制详解(一)

    系列目录 Binder机制详解(二) Binder机制详解(三) 文章目录 前言 一.爱情例子 1.普通Linux间进程通信方式 2.接着讲爱情的例子(Binder的实现机制) 3.Binder少拷贝 ...

  6. Hadoop中RPC机制详解之Server端

    2019独角兽企业重金招聘Python工程师标准>>> Hadoop 中 RPC 机制详解之 Client 端 1. Server.Listener RPC Client 端的 RP ...

  7. SSL / TLS 协议运行机制详解

    转载自  SSL / TLS 协议运行机制详解 互联网的通信安全,建立在SSL/TLS协议之上. 本文简要介绍SSL/TLS协议的运行机制.文章的重点是设计思想和运行过程,不涉及具体的实现细节.如果想 ...

  8. 抖音算法推荐机制详解

    抖音算法推荐机制详解!(科普向) 众所周知抖音的流量分配是去中心化的,这种去中心化算法,让每个人都有机会爆红,可为什么别人几个粉玩抖音,就能轻松获得10w+点赞?而你怒拍几十条也枉然? 抖音的游戏规则 ...

  9. 【大数据day14】——MapReduce的运行机制详解(案列:Reduce 端实现 JOIN, Map端实现 JOIN,求共同好友)

    文章目录 1 .MapReduce的运行机制详解 1.1:MapTask 工作机制 详细步骤 配置 1.2 :ReduceTask 工作机制 详细步骤 1.3:Shuffle 过程 2. 案例: Re ...

最新文章

  1. 马斯克将Roadster送上太空,“宇宙第一跑车”诞生
  2. 聊一聊IAR的workspace文件组织
  3. 【20:30直播】网易老司机聊程序员的职场道路选择
  4. 一步一步部署SSIS包图解教程1
  5. 浅谈c/c++typedef和#define区别[转]
  6. android逆向分析有什么用,如何开始对Android应用的逆向分析?
  7. Centos7.4 yum 安装MariaDB
  8. Filter过滤器执行流程
  9. 搜索算法-广度优先和深度优先搜索
  10. cygwin下各盘挂载点
  11. C#基础-Func,Action
  12. 【置顶】数字全息干涉测量技术研究现状
  13. 魅族路由器极速版刷机_[技术贴]路由器刷pandavan固件教程——以魅族路由器极速版为例...
  14. scrt设置右键粘贴,选中复制
  15. 1394接口_虽“老”却能战 了解主板旧接口
  16. Axure RP 9.0 中继器增删改查实现[原型图]
  17. 数据库--sql查询某一时间段数据
  18. 怎么把wav文件改成mp3?
  19. 计算机主机自动关机如何设置,WinXP电脑怎么设置自动关机?
  20. Java 程序员常用资源工具集合

热门文章

  1. 基于J2EE架构的项目开发团队中的角色与职责
  2. EventBus、Rxjava、RxBus的定义、作用、使用方式及区别
  3. 内容算法解读:提高内容摘要与原文的一致性(Faithfulness)
  4. java 之file文件/目录创建
  5. SpringBoot————Flyway的使用
  6. 前端面试----深信服面试题全概
  7. 如何将base64转化为图片
  8. 解决win10安装VC++ 出现的启动错误
  9. SOCKET的 10035错误
  10. python之信用卡ATM(第五天)