dubbo源码解析

Posted z街角的风铃y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dubbo源码解析相关的知识,希望对你有一定的参考价值。

 

  1. dubbo的spi机制源码流程

1.0 源码解读见dubbo官网:http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html

 

Dubbo源码解析

https://www.jianshu.com/nb/32484773

 

1.1 SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。

1.2总结:javaspi需要创建所有的实现类,且无法指定具体的实现类

1.3 Dubbo spi创建过程:

接口用@SPI标示,在META-INF/dubbo下创建名称是接口限定名的文件,文件用键值对便是,key自定义,value是实现累的限定名。

1.4 Dubbo源码流程:

l  首先通过 ExtensionLoader 的 getExtensionLoader 方法获取一个 ExtensionLoader 实例, getExtensionLoader 方法用于从缓存中获取与拓展类对应的 ExtensionLoader,若缓存未命中,则创建一个新的实例。

l  然后再通过 ExtensionLoader 的 getExtension 方法获取拓展类对象。这其中,检查缓存,缓存未命中则调用createExtension 方法创建拓展对象。

l  createExtension 方法包含了如下的步骤:

1)       通过 getExtensionClasses 获取该SPI标示的接口type文件夹下所有的拓展类,(先从缓存中读取没有就通过配置的文件读取)再获取指定的拓展类

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

3)       向拓展对象中注入依赖(springioc,遍历目标类的所有方法,获取setter方法通过反射实现依赖注入)

4)       将拓展对象包裹在相应的 Wrapper 对象中,返回该实例(通过装饰实现springaop)

 

  1. dubbo的自适应拓展源码
  2. https://www.jianshu.com/p/8c5211476c31

有时,有些拓展并不想在框架启动阶段被加载,而是希望在拓展方法被调用时,根据运行时参数进行加载。自适应拓展机制的实现逻辑比较复杂,首先 Dubbo 会为拓展接口生成具有代理功能的代码。,所有扩展点都通过传递 URL 携带配置信息。然后通过 javassist 或 jdk 编译这段代码,得到 Class 类。最后再通过反射创建代理类。

从上面的代码中可知,Adaptive 可注解在类或方法上。

    • 标注在类上
      Dubbo 不会为该类生成代理类。
    • 标注在方法上
      Dubbo 则会为该方法生成代理逻辑,表示当前方法需要根据 参数URL 调用对应的扩展点实现。

创建自适应拓展类步骤:

l  getAdaptiveExtension 方法是获取自适应拓展的入口方法,首先会检查缓存,缓存未命中就创建。

l  createAdaptiveExtension 方法,

1)       调用 getAdaptiveExtensionClass 方法获取自适应拓展 Class 对象,

2)       再通过反射进行实例化,

3)       然后调用 injectExtension 方法向拓展实例中注入依赖

l  getAdaptiveExtensionClass 方法

  1. 调用 getExtensionClasses 获取某个接口的所有的拓展类
  2. 检查cachedAdaptiveClass缓存,若缓存不为空,则返回缓存,如果某个实现类被 Adaptive 注解修饰了,那么该类就会被赋值给 cachedAdaptiveClass 变量,略过第三步。
  3. 若缓存为空,则调用createAdaptiveExtensionClass创建自适应拓展类

l  createAdaptiveExtensionClass:该方法首先会生成自适应拓展类的源码,然后通过 Compiler 实例(Dubbo 默认使用 javassist 作为编译器)编译源码,得到代理类 Class 实例。接下来,我们把重点放在代理类代码生成的逻辑上

  1. adaptive注解检测,检查接口是否有方法被该注解标示,都没有则抛出异常。
  2. 生成类
  3. 生成方法,未注解修饰的方法生成一句抛出异常,修饰的方法获取 URL 数据,并为之生成判空和赋值代码。
  4. 获取adaptive注解值
  5. 检测Invocation参数
  6. 生成拓展名获取逻辑,

生成拓展加载与目标方法调用逻辑,

比如

com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader

    .getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);

return extension.refer(arg0, arg1);

 

  1. dubbo服务暴露源码流程

(1)容器创建完之后会触发ServiceBean(实现了applicationLIstener接口)类中的ContextRefreshedEvent事件,执行export()方法。

(2)export()方法会调用ServiceConfig中的doExport()方法,这个方法会调用doExportUrls()方法,进而doExportUrlsFor1Protocol()方法。

(3)doExportUrlsFor1Protocol()方法中会利用反射构造invoker,这个invoker封装了服务实现类注册的地址及端口相关信息。同时执行protocol.export()方法。

(4)protocol.export()中的protocol有两个实现类,这个是最关键的,一个是RegistryProtocol一个是DubboProtocol,调用这个方法的时候会首先调用RegistryProtocol类,RegistryProtocol类中的export()方法会调用doLocalExport()方法通知DubboProtocol执行openServer(url)方法进行服务的开启,其实就是开启一个netty服务。同时export()方法会调用ProviderConsumerRegTable.registerProvider()方法进行注册表的缓存以及服务的注册。

 

  1. dubbo服务发现源码流程

在ReferenceBean->getObject()->init()中会调用createProxy()方法用来创建代理对象。

在createProxy()中会执行一个refprotocol.refer()方法,这里refprotocol同样有两个实现类,一个是RegistryProtocol,一个是DubboProtocol

RegistryProtocol负责注册信息,订阅信息,构造invoker代理类,并将消费者对于的invoke缓存到注册列表中。

DubboProtocol主要负责connect/getClients()连接获取客户端,等待与服务端通信

dubbo服务调用源码流程

 

  1. 框架整体设计

 

 

 

dubbo框架可以分为10层,而这10层又可以归为Business、RPC、Remoting这三层。

 

Business

Service业务层:业务代码的接口和实现。我们实际使用的Dubbo的业务层级。该层是与实际业务逻辑相关的,根据服务提供方和服务消费方的业务设计对应的接口和实现。

 

RPC

Config配置层: 对外的配置接口,以ServiceConfig和ReferenceConfig为中心,可以直接new配置类,也可以通过spring解析配置生成配置类。主要是dubbo的一些配置。

 

Proxy服务代理层:服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton, 扩展接口为ProxyFactory 。不论是Consumer还是Provider,Dubbo都会对其生成代理,在代理之间进行通信。

 

Registry注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactory, Registry, RegistryService。进行服务的注册与发现。

 

Cluster路由层:封装多个Provider的路由以及负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 Cluster, Directory, Router, LoadBalance。就是将多个服务组合起来形成一个大服务。

 

Monitor监控层:RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory, Monitor, MonitorService。

 

Remoting

protocol 远程调用层:封装 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporter。

 

exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer。

 

transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec。

 

serialize 数据序列化层:可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool。

 

以上是关于dubbo源码解析的主要内容,如果未能解决你的问题,请参考以下文章

合集DUBBO源码解析及最佳实践合集二十四篇

Dubbo原理和源码解析之服务暴露

Dubbo原理何源码解析之服务暴露

dubbo源码系列3——dubbo自定义标签解析

dubbo源码解析

dubbo源码解析-集群容错架构设计