Dubbo源码|十九、Dubbo服务引入——基本原理

398 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情

开篇

本文介绍Dubbo服务引入的过程的基本原理和思路。

我们在使用dubbo时,引入jar包,加上@DubboReference注解就能使用了,先来个简单示例。

@Service
public class DemoServiceImpl implements DemoService {
    @DubboReference
    private DemoService demoService;

    @Override
    public String sayHello(String name) {
        return demoService.sayHello(name);
    }
}

关于@DubboReference注解的解析可以参考之前的一篇文章:

Dubbo与Spring整合原理—@DubboReference

前面介绍了Dubbo服务暴露的过程,Dubbo服务暴露是将服务导出并注册到注册中心,那么Dubbo服务引入是和暴露的过程相反的,服务引入是从注册中心获取服务信息,然后创建代理对象,进行服务调用。

思路流程

可以大致想一下,服务引入的过程:

  1. 从注册中心获取服务提供者的列表
  2. 判断是否存在Mock、Stub、回调等
  3. 服务路由选择,从多个提供者里选出可用的提供者
  4. 从可用的服务提供者列表经过负载均衡选出1个进行调用
  5. 如果调用失败,进行集群容错的处理
  6. 初始化Netty准备调用
  7. 发送调用数据进行调用

概念

Dubbo为达成这种调用流程引入了几个概念

Invoker

Invoker是一个接口,他有多个实现类,比如:FailbackClusterInvoker FailoverClusterInvoker等等。

在执行Mock的时候,使用的是MockClusterInvoker。在这个Invoker类里面又会调用invoker.invoke()方法。

这是一种责任链的形式调用。

MockClusterInvoker -> FailoverClusterInvoker -> DubboInvoker

代理对象

我们知道被@DubboReference标记的属性会生成一个代理对象,那么这个代理对象内部是有个一个Invoker属性的,在执行的过程中,如果给这个Invoker属性赋值为MockClusterInvoker那么他就会有mock的功能,这也是面向接口编程的一种体现。

代理对象执行最简单的逻辑可以体现为,代理类内有个Invoker对象以及一个Invocation,在执行调用时,直接调用Invoker对象的invoke方法即可。

服务目录

消费者从注册中心获取提供者列表,一个具体的提供者对应一个DubboInvoker,这个提供者列表在获取后会被缓存起来,缓存的地方就被称为服务目录。

一个被@DubboReference注解标记的属性里就会有一个服务目录,服务目录存放了提供者列表,在代码中对应为List<Invoker>,这个Invoker其实就是DubboInvoker

那么构造一个服务目录,需要做什么工作呢?

  1. 从注册中心获取服务提供者列表。
  2. 把提供者列表解析成List<Invoker>
  3. 注册服务监听。
  4. 服务路由,筛选需要的服务提供者。
  5. 构造服务调用路由链,TagRouter->AppRouter->ServiceRouter等,同样的这里也需要监听。

这里的服务监听是针对消费端的服务监听,与提供者的服务监听类似,消费端也可以配置服务监听,可以在服务启动后,再去动态更改服务运行时的参数。比如,服务调用超时时间、负载均衡算法、根据ip限制哪些服务可以调用哪些服务不能被调用等等。

服务监听的动态配置,可以在dubbo-admin的控制台中进行配置和修改。修改后,dubbo就会收到通知,然后对服务进行对应的更改。消费端服务监听与提供者的服务监听有所不同,后面再对服务监听进行详细介绍。

后记

本文介绍了服务引入的基本原理以及几个概念,下篇开始对源码进行分析。