这次源码解析借鉴《肥朝》前辈的dubbo源码解析,进行源码学习。总结起来就是先总体,后局部.也就是先把需要注意的概念先抛出来,把整体架构图先画出来.让读者拿着"地图"跟着我的脚步,并且每一步我都提醒,现在我们在哪,我们下一步要做什么,这样才不会迷失方向。
总体概述
首先是总体出发了解整体的架构,涉及到概念,在学习dubbo会更加理解透彻。
下面对上面这张图做简要的分析:
(1)cluster是集群,主要是
Invoker
概念:
Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。它里面有一个很重要的方法 Result invoke(Invocation invocation)。
Invocation是会话域,它持有调用过程中的变量,比如方法名,参数等重要信息。
它有2种类型的Invoker
1.本地执行类的Invoker
server端:比如有一个dubbo接口demoService.sayHello,在本项目中执行 demoService.sayHello,就通过InjvmExporter来进行反射执行demoService.sayHello就可以了。
2.远程通信类的Invoker
client端:要执行 demoService.sayHello,它封装了DubboInvoker进行远程通信,发送要执行的接口给server端。
server端:采用了AbstractProxyInvoker执行了DemoServiceImpl.sayHello,然后将执行结果返回发送给client.
按服务提供、服务消费分类
引用官方文档:分为服务提供 Invoker 和服务消费 Invoker
为了更好的解释上面这张图,我们结合服务消费和提供者的代码示例来进行说明:
服务消费者代码:
public class DemoClientAction {
private DemoService demoService;
public void setDemoService(DemoService demoService) {
this.demoService = demoService;
}
public void start() {
String hello = demoService.sayHello("world" + i);
}
}
上面代码中的 DemoService 就是上图中服务消费端的 proxy,用户代码通过这个 proxy 调用其对应的 Invoker [5],而该 Invoker 实现了真正的远程服务调用。
服务提供者代码:
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) throws RemoteException {
return "Hello " + name;
}
}
上面这个类会被封装成为一个 AbstractProxyInvoker 实例,并新生成一个 Exporter 实例。这样当网络通讯层收到一个请求后,会找到对应的 Exporter 实例,并调用它所对应的 AbstractProxyInvoker 实例,从而真正调用了服务提供者的代码。
Invoker继承关系
Directory
概念
简单来说,Directory就是装载invoker的文件目录
两个重要Directory
StaticDirectory:静态目录服务,他的Invoker是固定的。
RegistryDirectory:注册目录服务,他的Invoker集合数据来源于zk注册中心的,他实现了NotifyListener接口,这个接口中的notify方法就是注册中心的回调,也就是它之所以能根据注册中心动态变化的根源所在.。
整个过程有一个重要的map变量,methodInvokerMap(它是数据的来源;同时也是notify的重要操作对象,重点是写操作。)
Router
概念
利用Router,可以从多个服务提者方中选择一个进行调用
分类
主要是3个实现类:
ConditionRouter(条件路由):条件路由主要就是根据dubbo管理控制台配置的路由规则来过滤相关的invoker
MockInvokersSelector:主要根据参数,判断是否需要筛选出正常的(非mock的)invoker 或者 mock的invoker
ScriptRouter(脚本路由):待补充
例子
参考:org.apache.dubbo.rpc.cluster.router.script.ScriptRouterTest
LoadBalance
概念
与Router功能类似,利用负载均衡策略(random,roundrobin,leastactive),从多个服务提者方中选择一个进行调用
Protocol
概念
Protocol 是服务域,它是 Invoker 暴露和引用的主功能入口,它负责 Invoker 的生命周期管理。
再接下来给大家一张"地图","地图"上我已经标记了序号,再下面的源码分析中,我也会实时提醒我们所在的位置,以至于不会迷失方向.
消费方调用过程中,dubbo究竟做了什么?
a、在Directory中找出本次集群中的全部invokers
b、在Router中,将上一步的全部invokers挑选出满足条件的invokers
c、在LoadBalance中,将上一步的能正常的执行invokers中,根据配置的负载均衡策略,挑选出需要执行的invoker
后面开始,就是正式的源码阅读(环境搭建这些略过)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。