开启掘金成长之旅!这是我参与「掘金日新计划 · 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服务引入是和暴露的过程相反的,服务引入是从注册中心获取服务信息,然后创建代理对象,进行服务调用。
思路流程
可以大致想一下,服务引入的过程:
- 从注册中心获取服务提供者的列表
- 判断是否存在Mock、Stub、回调等
- 服务路由选择,从多个提供者里选出可用的提供者
- 从可用的服务提供者列表经过负载均衡选出1个进行调用
- 如果调用失败,进行集群容错的处理
- 初始化Netty准备调用
- 发送调用数据进行调用
概念
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。
那么构造一个服务目录,需要做什么工作呢?
- 从注册中心获取服务提供者列表。
- 把提供者列表解析成
List<Invoker>。 - 注册服务监听。
- 服务路由,筛选需要的服务提供者。
- 构造服务调用路由链,
TagRouter->AppRouter->ServiceRouter等,同样的这里也需要监听。
这里的服务监听是针对消费端的服务监听,与提供者的服务监听类似,消费端也可以配置服务监听,可以在服务启动后,再去动态更改服务运行时的参数。比如,服务调用超时时间、负载均衡算法、根据ip限制哪些服务可以调用哪些服务不能被调用等等。
服务监听的动态配置,可以在dubbo-admin的控制台中进行配置和修改。修改后,dubbo就会收到通知,然后对服务进行对应的更改。消费端服务监听与提供者的服务监听有所不同,后面再对服务监听进行详细介绍。
后记
本文介绍了服务引入的基本原理以及几个概念,下篇开始对源码进行分析。