网易首页 > 网易号 > 正文 申请入驻

看大牛是如何一次性把RPC远程过程调用,Dubbo架构进阶给讲清的

0
分享至

  ◆ Dubbo架构进阶

  Dubbo架构主要包含四个角色:消费者、提供者、注册中心和监控系统,如下图所示。

  具体的交互流程是:消费者(Consumer)通过注册中心获取提供者(Provider)节点后,通过Dubbo的客户端SDK与Provider建立连接,并发起调用。Provider通过Dubbo的服务端SDK接收Consumer的请求,处理后再把结果返回给Consumer。

  对于采用Dubbo进行RPC调用的解决方案,消费者和提供者都需要引入Dubbo的SDK来完成远程调用。因为Dubbo本身是采用Java实现的,所以要求服务消费者和服务提供者也都必须采用Java实现。不过开源社区已经开始使用对核心扩展点进行TCK(Technology CompatibilityKit)提升框架的兼容性。它为用户增加一种扩展实现,只需通过TCK,即可确保与框架的其他部分兼容运行,可以有效提高健壮性,也方便第三方接入。下面是Dubbo的官方详细架构。

  左边部分是服务消费者使用的接口,右边部分是服务提供者使用的接口,位于中轴线上的为双方都用到的接口。

  ● 从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系,每一层都可以剥离上层被复用,其中Service 和 Config 层 为 API , 其 他 各 层 均 为 SPI ( ServiceProvider Interface)。

  ● 浅色小块为扩展接口,深色小块为实现类,图中只显示用于关联各层的实现类。

  ● 深色虚线为初始化过程,即启动时组装链,红色实线为方法调用过程,即运行时调时链,紫色三角箭头为继承(读者可到官网查看彩色图片),可以把子类看作父类的同一个节点,线上的文字为调用的方法。Dubbo服务调用过程Dubbo服务调用过程比较复杂,包含众多步骤,比如发送请求、编解码、服务降级、过滤器链处理、序列化、线程派发及响应请求等。

  下面我们重点分析请求的发送与接收、编解码、线程派发及响应的发送与接收等过程。

  ◆ Dubbo的服务调用过程

  如下图所示。

  首先服务消费者通过代理对象Proxy发起远程调用,接着通过网络客户端Client将编码后的请求发送给服务提供者的网络层,也就是Server。Server在收到请求后,首先要做的事情是对数据包进行解码。然后将解码后的请求发送至分发器Dispatcher,再由分发器将请求派发到指定的线程池上,最后由线程池调用具体的服务。这就是一个远程调用请求的发送与接收过程。

  ◆ 服务消费者发送请求

  Dubbo支持同步和异步两种调用方式,其中异步调用还可细分为“有返回值”的异步调用和“无返回值”的异步调用。所谓“无返回值”的异步调用是指服务消费者只管调用,但不关心调用结果,此时Dubbo会直接返回一个空的RpcResult。若要使用异步特性,需要服务消费者手动进行配置。默认情况下,Dubbo使用同步调用方式。服务调用的线程栈快照如下图所示。

  ◆ 服务提供者接收请求

  默认情况下,Dubbo使用Netty作为底层的通信框架。Netty首先会通过解码器对数据进行解码,并将解码后的数据传递给下一个处理器的指定方法。

  解 码 器 将 数 据 包 解 析 成 Request 对 象 后 , NettyHandler 的messageReceived方法紧接着会收到这个对象,并将这个对象继续向下传 递 。其 间 该 对 象 会 被 依 次 传 递 给 NettyServer 、MultiMessageHandler、HeartbeatHandler以及AllChannelHandler处理。最后由AllChannelHandler将该对象封装到Runnable实现类对象中,并将Runnable放入线程池中执行后续的调用逻辑,调用栈如下图所示。

  Dispatcher就是线程派发器。需要说明的是,Dispatcher真实的职 责 是 创 建 具 有 线 程 派 发 能 力 的 ChannelHandler , 比 如AllChannelHandler、MessageOnlyChannelHandler和ExecutionChannelHandler等,其本身并不具备线程派发能力。Dubbo的5种不同的线程派发策略如下表所示。

  默认配置下,Dubbo使用all派发策略,即将所有的消息都派发到线 程 池 。请 求 对 象 会 被 封 装 在 ChannelEventRunnable 中 ,ChannelEventRunnable将会是服务调用过程的新起点。所以接下来我们看一下以ChannelEventRunnable为起点的服务提供者的线程调用栈,如下图所示。

  
◆ 向用户线程传递调用结果

  响应数据解码完成后,Dubbo会将响应对象派发到线程池。要注意的是,线程池中的线程并非用户的调用线程,所以要想办法将响应对象从线程池传递到用户线程上。

  用户线程在发送完请求后,调用DefaultFuture的get方法等待响应对象的到来。当响应对象到来后,用户线程会被唤醒,并通过调用编号获取属于自己的响应对象。

  ◆ Dubbo设计原理

  Dubbo在架构上通过SPI机制(SPI的全称为Service ProviderInterface,SPI机制是一种服务发现机制)的设计,使得整体架构具备了极高的可扩展性。

  下面是Dubbo的核心设计原理:

  ● 采 用 Microkernel+Plugin 模 式 , Microkernel 负 责 组 装Plugin,Dubbo自身的功能也是通过扩展点实现的,也就是Dubbo的所有功能点都可被用户自定义扩展所替换。

  ● 采用URL作为配置信息的统一格式,所有扩展点都通过传递URL携带配置信息。

  SPI机制的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类,这样它可以在运行时动态为接口替换实现类。正因为此特性,我们可以通过SPI机制为程序提供拓展功能,这样可以在运行时动态为接口替换实现类。Dubbo就是通过SPI机制加载所有组件的,不过Dubbo并未使用Java原生的SPI机制,而是对其进行了增强,使其能够更好地满足需求。

  ◆ Dubbo SPI示例

  首先,我们定义一个接口,名称为Hello:

  Dubbo SPI的相关逻辑被封装在了ExtensionLoader类中,通过ExtensionLoader类我们可以加载指定的实现类。Dubbo SPI所需的配置文件需放置在META-INF/dubbo路径下,配置内容如下:

  与Java SPI实现类配置不同,Dubbo SPI通过键值对的方式进行配置,我们可以按需加载指定的实现类。另外,在测试Dubbo SPI时,需要在Robot接口上标注@SPI注解。

  上述代码的输出结果如下:

  
◆ SPI机制

  下面我们结合源码来理解Dubbo的SPI机制和整体架构特性,需要明确几个核心概念,如下图所示。

  ● ExtensionLoader

  ExtensionLoader作为整个SPI机制的核心起着无可替代的作用,扩展点并不会强制所有用户都使用Dubbo提供的某些架构。例如Dubbo提供了ZooKeeper注册中心,但是如果我们更倾向于其他的注册中心,我们可以替换掉Dubbo提供的注册中心。我们称这种可被替换的技术实现点为扩展点,类似的扩展点有很多,例如Protocol、Filter、Loadbalance等。

  鉴 于 ExtensionLoader 的 用 法 比 较 多 , 下 面 我 们 以ExtensionLoader 类 作 为 入 口 进 行 讲 解 。首 先 , 我 们 通 过ExtensionLoader的getExtensionLoader方法获取一个单例实例,然后通过ExtensionLoader的getExtension方法获取拓展类对象。其中,getExtensionLoader 方 法 用 于 从 缓 存 中 获 取 与 拓 展 类 对 应 的ExtensionLoader实例,若缓存未命中,则创建一个新的实例。下面我们以ExtensionLoader的getExtension方法作为入口,代码如下:

  上面代码的逻辑比较简单,首先检查缓存,缓存未命中则创建拓展对象。下面我们来看一下创建实例化对象的代码实现:

  createExtension模块中包含了如下步骤:

  (1)通过getExtensionClasses获取所有的拓展类。

  (2)通过反射创建拓展对象。

  (3)向拓展对象中注入依赖。

  (4)将拓展对象包裹在相应的Wrapper对象中。

  我们在通过名称获取拓展类之前,需要根据配置文件解析出拓展项名称到拓展类的映射关系表(Map<名称,拓展类>),之后再根据拓展项名称从映射关系表中取出相应的拓展类即可。相关过程的代码如下:

  这里也是先检查缓存,若缓存未命中则通过synchronized加锁,加锁后再次检查缓存,并判空。此时如果classes仍空,则通过loadExtensionClasses加载拓展类。

  下面分析loadExtensionClasses方法的逻辑:

  loadExtensionClasses方法总共做了两件事情,一是对SPI注解进行解析,二是调用loadDirectory方法加载指定目录中的配置文件。

  SPI注解解析过程比较简单,loadDirectory方法先通过类加载器获 取 所 有 资 源 链 接 , 然 后 通 过 loadResource 方 法 加 载 资 源 。

  loadResource方法用于读取和解析配置文件,并通过反射加载类,最后调用loadClass方法进行其他操作。Dubbo会从以下三个路径读取并加载扩展点配置文件:

  ● Wrapper

  在实例化扩展点的代码中可以看到,在加载某个接口的扩展类时,如果某个实现中有一个拷贝类构造函数,那么该接口实现就是该接口的包装类,此时Dubbo会在真正的实现类上层包装上Wrapper。即这个时候从ExtensionLoader中返回的实际扩展类是被Wrapper包装的接口实现类。在上文代码的createExtension(String name)实例化扩展点中(代码1#)可以看到相关代码实现:将反射创建的instance实例作为参数传给Wrapper的构造方法,并通过反射创建Wrapper实例 , 而 后 在 Wapper 实 例 中 注 入 依 赖 , 最 后 将 Wapper 实 例 赋 值 给instance实例。

  ● Setter

  Dubbo IoC通过setter方法注入依赖。Dubbo首先会通过反射获取实例的所有方法,然后遍历方法列表,检测方法名是否具有setter方法特征。若有这个特征则通过ObjectFactory获取依赖对象,最后通过反射调用setter方法将依赖设置到目标对象中。整个过程对应的注入扩展点代码如下:

  扩展点实现类的成员如果为其他扩展点类型,ExtensionLoader会自动注入依赖的扩展点。ExtensionLoader通过扫描扩展点实现类的所有set方法来判定其成员。

  ● @SPI

  在SPI代码实例中,Dubbo只有接口类使用了@SPI注解才会去加载扩展点实现,Dubbo本身重新实现了一套SPI机制,支持AOP与依赖注入,并且可以利用缓存提升加载实现类的性能,也支持实现类的灵活获取。下面是@SPI的定义:

  在上文的loadExtensionClasses中(代码2#)中,我们可以看到getExtensionLoader会对传入的接口进行校验,其中就会检验接口是否被@SPI注解,通过获取并缓存接口的@SPI注解上的默认实现类cacheDefaultExtensionName,再调用loadDirectory方法记载指定目录中的配置文件。源码实现如下:

  ● @Adaptive

  在 Dubbo 中 , 很 多 扩 展 都 是 通 过 SPI 机 制 进 行 加 载 的 , 比 如Protocol、Cluster、LoadBalance等。然而有些扩展并不想在框架启动阶段被加载,而是希望在扩展方法被调用时根据运行时参数进行加载。

  在对自适应扩展生成过程进行深入分析之前,我们来看一下与自适应扩展息息相关的一个注解,即@Adaptive注解,该注解的定义如下:

  @Adaptive可注解在类或方法上。当@Adaptive注解在类上时,Dubbo不会为该类生成代理类。当@Adaptive注解在方法(接口方法)上时,Dubbo则会为该方法生成代理逻辑。@Adaptive注解在类上的情况 很 少 , 在 Dubbo 中 仅 有 两 个 类 被 @Adaptive 注 解 了 , 分 别 是AdaptiveCompiler和AdaptiveExtensionFactory。

  getAdaptiveExtension方法是获取自适应扩展的入口方法,相关代码如下:

  getAdaptiveExtension方法首先会检查缓存,如果缓存未命中,则 调 用 方 法 创 建 自 适 应 扩 展 。下 面 我 们 看 一 下createAdaptiveExtension方法的代码:

  createAdaptiveExtension方法的代码包含了三个逻辑,分别如下:

  ○ 调 用 getAdaptiveExtensionClass 方 法 获 取 自 适 应 扩 展Class对象。

  ○ 通过反射进行实例化。

  ○ 调用injectExtension方法向扩展实例中注入依赖。

  ● @Activate

  @Activate注解表示一个扩展是否被激活,可以放在类定义和方法上,Dubbo将它用在SPI扩展类定义上,表示这个扩展实现的激活条件和时机。下面是代码示例:

  上 述 示 例 表 示 只 有 当 group 参 数 作 为 提 供 者 时 才 会 使RpcServerInterceptor拦截逻辑生效,这个注解的作用和Spring Boot中的@Condition注解类似。

  免责声明:

  本号部分分享的资料来自网络收集和整理,所有文字和图片版权归属于原作者所有,且仅代表作者个人观点,与本号无关,文章仅供读者学习交流使用,并请自行核实相关内容,如文章内容涉及侵权,请联系后台管理员删除。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
后续!北京使馆车大妈身份遭曝光,原来大有来头,胡锡进发声

后续!北京使馆车大妈身份遭曝光,原来大有来头,胡锡进发声

科学发掘
2024-06-19 03:23:18
欧洲杯经典1幕:39岁C罗挥拳,挑衅怒吼门将!小弟帮他复仇

欧洲杯经典1幕:39岁C罗挥拳,挑衅怒吼门将!小弟帮他复仇

叶青足球世界
2024-06-19 05:18:14
普京到访朝鲜,要谈两件大事,一件关乎中国东北,一件为反击美国

普京到访朝鲜,要谈两件大事,一件关乎中国东北,一件为反击美国

说天说地说实事
2024-06-18 16:24:00
再见了!独行侠!输球后,他正式退出NBA...

再见了!独行侠!输球后,他正式退出NBA...

小鬼头体育
2024-06-19 03:41:11
全新技术光刻薄膜量产,下代光刻机出现,芯片将从纳米到皮米级!

全新技术光刻薄膜量产,下代光刻机出现,芯片将从纳米到皮米级!

嘿哥哥科技
2024-06-19 17:11:28
突发!上海地铁惊现持刀伤人事件,现场曝光引发热议!

突发!上海地铁惊现持刀伤人事件,现场曝光引发热议!

小毅讲历史
2024-06-19 13:48:25
都在说“作战中心”,这到底是个什么单位?

都在说“作战中心”,这到底是个什么单位?

大猫财经Pro
2024-06-19 18:40:54
大瓜!狗仔直播曝陈晓8年婚姻破裂,提离婚净身出户拉黑陈妍希

大瓜!狗仔直播曝陈晓8年婚姻破裂,提离婚净身出户拉黑陈妍希

花花lo先森
2024-06-19 13:58:20
为什么我妈妈瞧不起我爸爸? 看网友的评论引起万千共鸣!

为什么我妈妈瞧不起我爸爸? 看网友的评论引起万千共鸣!

娱乐洞察点点
2024-06-19 07:42:08
血糖又有新标准?3.9-6.1已成历史,不同年龄标准不同,不妨自查

血糖又有新标准?3.9-6.1已成历史,不同年龄标准不同,不妨自查

今日养生之道
2024-06-18 20:29:32
关于姜萍,中科院士袁亚湘:凭刷题获得高分的人大多没有创新能力

关于姜萍,中科院士袁亚湘:凭刷题获得高分的人大多没有创新能力

秋姐居
2024-06-19 18:28:51
俄乌前线相对平静,北约、俄、乌高层频频交锋,还得对耗下去

俄乌前线相对平静,北约、俄、乌高层频频交锋,还得对耗下去

战域笔墨
2024-06-19 18:02:08
更多细节曝光!中国海警“大刀队”给菲律宾特种部队缴械了?

更多细节曝光!中国海警“大刀队”给菲律宾特种部队缴械了?

军武次位面
2024-06-19 18:06:32
普京访朝获高规格接待,韩国对华转达关切,并当面向中方提出要求

普京访朝获高规格接待,韩国对华转达关切,并当面向中方提出要求

王墨观察
2024-06-19 14:18:07
突发!上海地铁发生持刀伤人案,3人受伤,凶手已抓,大V老胡发声

突发!上海地铁发生持刀伤人案,3人受伤,凶手已抓,大V老胡发声

影视解说阿相
2024-06-19 15:08:18
女排总决赛来袭!CCTV-5不直播,球迷无福消受,附具体赛程如下

女排总决赛来袭!CCTV-5不直播,球迷无福消受,附具体赛程如下

邮轮摄影师阿嗵
2024-06-19 07:50:43
近期在与老公过性生活时,我察觉到他和过去这十几年有着不太一样

近期在与老公过性生活时,我察觉到他和过去这十几年有着不太一样

第7情感
2024-06-18 12:23:00
爆足协启动两名归化球员程序,伊万有福,国足冲击世界杯渐露曙光

爆足协启动两名归化球员程序,伊万有福,国足冲击世界杯渐露曙光

邮轮摄影师阿嗵
2024-06-19 18:33:11
欧洲都在猛夸C罗!唯有中国记者敢说:葡萄牙不该让他首发

欧洲都在猛夸C罗!唯有中国记者敢说:葡萄牙不该让他首发

球事百科吖
2024-06-19 08:05:16
拥有外交豁免权的余琦,到底是什么级别

拥有外交豁免权的余琦,到底是什么级别

娱乐小可爱蛙
2024-06-19 15:17:22
2024-06-19 19:26:44
IT架构师联盟
IT架构师联盟
IT架构实战分享
689文章数 7654关注度
往期回顾 全部

科技要闻

英伟达超越苹果、微软登顶全球新股王

头条要闻

胖东来"爆改"的永辉超市营业挤满顾客:员工月薪涨千元

头条要闻

胖东来"爆改"的永辉超市营业挤满顾客:员工月薪涨千元

体育要闻

欧洲杯最大的混子,非他莫属

娱乐要闻

黄一鸣“杀疯了” 直播间卖大葱养孩子

财经要闻

深化科创板改革 证监会发布八条措施

汽车要闻

双肾格栅变化大/内饰焕新 新一代宝马X3官图发布

态度原创

旅游
时尚
教育
亲子
公开课

旅游要闻

遭遇极端高温天气导致希腊多名游客死亡

50岁女人为什么不能乱穿衣?看了她们的造型就懂了,会穿才美

教育要闻

孩子买学习机,到底该关注哪些核心问题才能不踩坑?

亲子要闻

有些家长的无知能到什么程度?看文字都感觉窒息!毁了孩子一生!

公开课

近视只是视力差?小心并发症

无障碍浏览 进入关怀版