20. Dubbo服务引入 - 基本原理
1. 开篇
本文介绍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服务引入是和暴露的过程相反的,服务引入是从注册中心获取服务信息,然后创建代理对象,进行服务调用。
2. 思路流程
可以大致想一下,服务引入的过程:
- 从注册中心获取服务提供者的列表
- 判断是否存在Mock、Stub、回调等
- 服务路由选择,从多个提供者里选出可用的提供者
- 从可用的服务提供者列表经过负载均衡选出1个进行调用
- 如果调用失败,进行集群容错的处理
- 初始化Netty准备调用
- 发送调用数据进行调用
3. 概念
Dubbo为达成这种调用流程引入了几个概念
3.1 Invoker
Invoker是一个接口,他有多个实现类,比如:FailbackClusterInvoker
、 FailoverClusterInvoker
等等。
在执行Mock
的时候,使用的是MockClusterInvoker
。在这个Invoker
类里面又会调用invoker.invoke()
方法。
这是一种责任链的形式调用。
MockClusterInvoker
-> FailoverClusterInvoker
-> DubboInvoker
。
3.2 代理对象
我们知道被@DubboReference
标记的属性会生成一个代理对象,那么这个代理对象内部是有个一个Invoker
属性的,在执行的过程中,如果给这个Invoker
属性赋值为MockClusterInvoker
那么他就会有mock的功能,这也是面向接口编程的一种体现。
代理对象执行最简单的逻辑可以体现为,代理类内有个Invoker
对象以及一个Invocation
,在执行调用时,直接调用Invoker
对象的invoke
方法即可。
3.3 服务目录
消费者从注册中心获取提供者列表,一个具体的提供者对应一个DubboInvoker
,这个提供者列表在获取后会被缓存起来,缓存的地方就被称为服务目录。
一个被@DubboReference
注解标记的属性里就会有一个服务目录,服务目录存放了提供者列表,在代码中对应为List<Invoker>
,这个Invoker
其实就是DubboInvoker
。
那么构造一个服务目录,需要做什么工作呢?
- 从注册中心获取服务提供者列表。
- 把提供者列表解析成
List<Invoker>
。 - 注册服务监听。
- 服务路由,筛选需要的服务提供者。
- 构造服务调用路由链,
TagRouter
->AppRouter
->ServiceRouter
等,同样的这里也需要监听。
这里的服务监听是针对消费端的服务监听,与提供者的服务监听类似,消费端也可以配置服务监听,可以在服务启动后,再去动态更改服务运行时的参数。比如,服务调用超时时间、负载均衡算法、根据ip限制哪些服务可以调用哪些服务不能被调用等等。
服务监听的动态配置,可以在dubbo-admin
的控制台中进行配置和修改。修改后,dubbo
就会收到通知,然后对服务进行对应的更改。消费端服务监听与提供者的服务监听有所不同,后面再对服务监听进行详细介绍。
4. 后记
本文介绍了服务引入的基本原理以及几个概念,下篇开始对源码进行分析。