服务引用的大致流程
Provider将自己的服务暴露出来,注册到注册中心,而Consumer无非就是通过一系列操作从注册中心得知Provider信息,然后封装一个调用类和Provider进行深入的交流。
dubbo的一个可执行体就是Invoker, 所有的调用都要向Invoker靠拢,因为可以判断出应该要先生成一个Invoker,然后又因为框架需要往不侵入业务代码的方向发展,那我们的Consumer需要无感知的调用远程接口,因为需要搞一个代理类,包装一下屏蔽底层的细节。
整体大致流程如下:
ReferenceConfig -> Protocol -> Invoker -> ProxyFactory -> 代理实现
服务引入的时机
和服务暴露一样,是通过Spring的自定义标签机制解析生成对应的bean。
- Provider Service对应的解析就是Service Bean
- Consumer Reference 对应的是ReferenceBean
Spring容器刷新完成之后开始暴露,而服务引入的时机主要有两种,第一种是饿汉式,第二种是懒汉式。
饿汉式是通过InitializingBean接口中的afterPropertiesSet方法,容器通过调用ReferenceBean的afterPropertiesSet方法时引入服务。
懒汉式是只有当这个服务被注入到其他类中时启动引入流程,俨然就是说用到了才会服务引用。
- 默认情况下,dubbo采用懒汉式引入服务。如果需要饿汉式,可通过配置dubbo:reference的init属性开启。
- ReferenceBean还实现了FactoryBean接口
扩展:BeanFactory FactoryBean ObjectFactory
从字面上来说,BeanFactory、ObjectFactory是个工厂,FactoryBean是个Bean.
BeanFactory其实就是IOC容器,简单的说就是Spring里面的bean都归他管,而FactoryBean也是Bean,也归BeanFactory管。
那FactoryBean到底是个什么Bean呢? 他其实就是把你真实想要的bean封装了一层,在真正要获取这个Bean的时候,容器调用FactoryBean # getObject方法,而在这个方法里面你可以进行一些复杂的组装操作。
这个方法封装了真实想要的对象复杂的组装过曾。
ObjectFactory这个是用于延迟查找的场景,它就是一个普通工厂,当得到ObjectFactory对象时,相当于Bean没有被创建,只有当getObject()方法时 ,才会触发Bean实例化等生命周期。
总结:BeanFactory就是IOC容器,FactoryBean是特殊的Bean,用来封装创建比较复杂的对象,而ObjectBean主要用于延迟查找的场景、延迟实例化对象。
服务引用的三种方式
- 本地引入
- 直接远程引入
- 通过注册中心引入
本地引入:服务暴露的流程每个服务都会通过搞一个本地暴露,走injvm协议(当然要是scope=remote就没有本地引用了),因为存在一个服务端既是Provider又是Consumer的情况,然后有可能自己调用自己的服务,因为就弄了一个本地引入,这样就避免了远程网络调用的开销。
所以服务引入会先去本地缓存找找看有没有本地服务。
直接远程引入服务,这个其实就是平时测试的情况下使用,不需要启动注册中心,由Consumer直接配置写死Provider的地址,然后直连即可。
注册中心引入服务:重点!!! Consumer通过注册中心得知Provider的相关信息,然后进行服务的引入,这里还包括多注册中心,同一个服务多个提供者的情况,如何抉择如何封装,如何进行负载均衡、容错并且让使用者无感知,这个就是技术活。
dubbo如何做的?服务引入流程解析
默认是懒汉式的,所以服务引入的入口就是ReferenceBean 的 getObject方法。
首先先检查配置,通过配置构建一个map,然后利用map来构建URL,再通过URL上的协议利用自适应扩展机制调用对应的protocol.refer得到对应的invoker.
在多个URL的时候,先遍历构建出invoker然后再由StaticDirectory封装一下,然后通过cluster合并,只暴露出一个invoker.
然后再构建代理,封装invoker返回服务引用,之后Consumer调用的就是这个代理类。