dubbo服务引用源码分析

4 篇文章 0 订阅

dubbo服务引用流程大致如下:

(1)首先在dubbo容器启动的时候,会扫描所有的reference配置(也就是dubbo客户端配置的远程引用),生成对应ReferenceBean,例如:客户端的DemoClient类依赖了远程服务DemoService,那么dubbo就会生成一个ReferenceBean<DemoService>

(2)spring容器在初始化本地的bean的时候,发现DemoClient类依赖了DemoService类,于是spring会寻找DemoService的工厂类,结果就找到了ReferenceBean<DemoService>

(3)spring会调用ReferenceBean的getObject方法,以获得一个DemoService实例,ReferenceBean的getObject方法会调用调用ReferenceConfig的createProxy()方法,构建Invoker 实例以及远程服务的代理对象,然后返回这个对象

(4)然后客户端就可以通过这个代理对象执行的对远程服务的调用了

从上面的流程中我们可以看出createProxy()方法是一个关键,接下来我们就来看看这个方法执行了什么操作吧

(1)首先就是我们上面提到的创建Invoker的流程了,主要流程如下所示:

  1. 按照惯例,在进行具体工作之前,需先进行配置检查与收集工作
  2. 接着根据收集到的信息决定服务引用的方式,有三种:

本地 (JVM) 服务引用、直连方式引用远程服务、注册中心引用远程服务

  1. 不管是哪种引用方式,最后都会得到一个 Invoker 实例
  2. Invoker拥有调用本地或远程服务的能力(通过组合protocol生成的ExchangeClient对象获得远程通信的能力)

 

(2)创建了Invoker之后,ReferenceConfig会调用ProxyFactory类的getProxy()方法,会通过调用Dubbo的Proxy类而不是java的Proxy类,创建一个被动态代理的远程服务的代理对象(关键就在于这个proxy)

(3)客户端调用代理对象的时候,会被InvokerInvocationHandler动态代理拦截到,InvokerInvocationHandler中的invoke方法会执调用Invoker的invoke()方法

(4)我们知道Invoker拥有调用本地或远程服务的能力,其实就是如通过在invoke()方法里面,调用ExchangeClient进行网络通信

dubbo获得远程服务代理对象时序图:

 

流程其他关键点:

(1)Dubbo 服务引用的时机

上面为了简化流程我们没有提到,实际上Dubbo 服务引用的时机有两个:

  • 第一个是在 Spring 容器调用 ReferenceBean 的 afterPropertiesSet 方法时引用服务(这也是bean的生命周期中的方法,其会在对应bean的所有属性都初始化完成之后被调用)
  • 第二个是在 ReferenceBean 对应的服务被注入到其他类中时引用(ReferenceBean 实现了FactoryBean,因此会被spring当做一个生产bean的工厂)(依赖注入,并不是在运行的时候,如果是被单例bean引用,在springIOC容器初始化之后,执行以来注入的时候就会被引用)

这两个引用服务的时机区别在于,第一个是饿汉式的,第二个是懒汉式的。默认情况下,Dubbo 使用懒汉式引用服务。如果需要使用饿汉式,可通过配置 <dubbo:reference> 的 init 属性开启

(2)多个注册中心的invoker

如果有多个注册中心,此时需要通过集群管理类 Cluster 将多个 Invoker 合并成一个实例。合并后的 Invoker 实例同样具备调用本地或远程服务的能力

(3)动态代理的实现机制

dubbo通过代理工厂类 (ProxyFactory) 为服务接口生成代理类Proxy,默认是使用Javassist生成的Proxy

Invoker

Invoker 是 Dubbo 的核心模型,代表一个可执行体。在服务提供方,Invoker 用于调用服务提供类。在服务消费方,Invoker 用于执行远程调用。Invoker 是由 Protocol 实现类构建而来(也就是说或是不同的协议提供不同的Invoker,从中我们可以嗅到什么味道?我们知道协议不同,底层通信机制不同,Invoker下面应该也有对应的通信机制)

 

果然DubboInvoker中组合了ExchangeClient,但是ExchangeClient其实并不具备通信能力,它需要基于更底层的客户端实例进行通信。比如 NettyClient、MinaClient 等,默认情况下,Dubbo 使用 NettyClient 进行通信

 

ExchangeClient 客户端是 Exchangers 的 connect 方法被调用的时候创建的,会通过 SPI 机制加载指定的 HeaderExchangeClient 实例,默认是HeaderExchangeClient,

 

HeaderExchangeClient需要使用底层通信机制就需要,组合dubbo的transport层的对象,假如我们是使用的dubbo协议暴露服务,那么Transporters就会通过SPI机制返回一个NettyTransporter,在往下就是通过 Netty 提供的 API 构建 Netty 客户端了

 

Invoker的封装

  • Invoker 是 Provider 的一个可调用 Service 的抽象, Invoker 封装了 Provider 地址及 Service 接口信息
  • Directory 维护服务列表,每个服务被封装成一个 Invoker ,可以把它看成 List<Invoker> ,但与 List 不同的是,它的值可能是动态变化的,比如注册中心推送变更
  • Cluster 将 Directory 中的多个 Invoker 伪装成一个 Invoker ,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个
  • Router 负责从多个 Invoker 中按路由规则选出子集,比如读写分离,应用隔离等
  • LoadBalance 负责从多个 Invoker 中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值