dubbo源码解析
Posted z街角的风铃y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dubbo源码解析相关的知识,希望对你有一定的参考价值。
- 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)
- dubbo的自适应拓展源码
- 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 方法
- 调用 getExtensionClasses 获取某个接口的所有的拓展类
- 检查cachedAdaptiveClass缓存,若缓存不为空,则返回缓存,如果某个实现类被 Adaptive 注解修饰了,那么该类就会被赋值给 cachedAdaptiveClass 变量,略过第三步。
- 若缓存为空,则调用createAdaptiveExtensionClass创建自适应拓展类
l createAdaptiveExtensionClass:该方法首先会生成自适应拓展类的源码,然后通过 Compiler 实例(Dubbo 默认使用 javassist 作为编译器)编译源码,得到代理类 Class 实例。接下来,我们把重点放在代理类代码生成的逻辑上
- adaptive注解检测,检查接口是否有方法被该注解标示,都没有则抛出异常。
- 生成类
- 生成方法,未注解修饰的方法生成一句抛出异常,修饰的方法获取 URL 数据,并为之生成判空和赋值代码。
- 获取adaptive注解值
- 检测Invocation参数
- 生成拓展名获取逻辑,
生成拓展加载与目标方法调用逻辑,
比如
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);
- 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()方法进行注册表的缓存以及服务的注册。
- dubbo服务发现源码流程
在ReferenceBean->getObject()->init()中会调用createProxy()方法用来创建代理对象。
在createProxy()中会执行一个refprotocol.refer()方法,这里refprotocol同样有两个实现类,一个是RegistryProtocol,一个是DubboProtocol
RegistryProtocol负责注册信息,订阅信息,构造invoker代理类,并将消费者对于的invoke缓存到注册列表中。
DubboProtocol主要负责connect/getClients()连接获取客户端,等待与服务端通信
dubbo服务调用源码流程
- 框架整体设计
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源码解析的主要内容,如果未能解决你的问题,请参考以下文章