Directory代表多个Invoker,可以把它看成List,但与List不同的是,它的值可能是动态变化的,比如注册中心推送变更。Cluster将Directory中的多个Invoker伪装成一个Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个。

上面是文档上对Directory的解释。

Directory接口

Directory接口继承了Node接口:

1
2
3
4
5
6
7
public interface Directory<T> extends Node {
//获取服务类型
Class<T> getInterface();

//invoker列表,服务的列表
List<Invoker<T>> list(Invocation invocation) throws RpcException;
}

AbstractDirectory

默认实现为AbstractDirectory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
public abstract class AbstractDirectory<T> implements Directory<T> {

// 日志输出
private static final Logger logger = LoggerFactory.getLogger(AbstractDirectory.class);
//服务url
private final URL url ;
private volatile boolean destroyed = false;
//消费者url
private volatile URL consumerUrl ;
//路由
private volatile List<Router> routers;

public AbstractDirectory(URL url) {
this(url, null);
}

public AbstractDirectory(URL url, List<Router> routers) {
this(url, url, routers);
}

public AbstractDirectory(URL url, URL consumerUrl, List<Router> routers) {
if (url == null)
throw new IllegalArgumentException("url == null");
this.url = url;
this.consumerUrl = consumerUrl;
setRouters(routers);
}
//对list方法的默认实现
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
if (destroyed){
throw new RpcException("Directory already destroyed .url: "+ getUrl());
}
//获取Invoker列表的具体实现由具体子类实现
List<Invoker<T>> invokers = doList(invocation);
//路由
List<Router> localRouters = this.routers; // local reference
if (localRouters != null && localRouters.size() > 0) {
for (Router router: localRouters){
try {
if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY, true)) {
//路由
invokers = router.route(invokers, getConsumerUrl(), invocation);
}
} catch (Throwable t) {
logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
}
}
}
return invokers;
}

public URL getUrl() {
return url;
}

public List<Router> getRouters(){
return routers;
}

public URL getConsumerUrl() {
return consumerUrl;
}

public void setConsumerUrl(URL consumerUrl) {
this.consumerUrl = consumerUrl;
}
//构造中调用的设置路由的方法
protected void setRouters(List<Router> routers){
// copy list
routers = routers == null ? new ArrayList<Router>() : new ArrayList<Router>(routers);
// append url router
String routerkey = url.getParameter(Constants.ROUTER_KEY);
//指定了router,就使用制定的router来获取扩展实现
if (routerkey != null && routerkey.length() > 0) {
RouterFactory routerFactory = ExtensionLoader.getExtensionLoader(RouterFactory.class).getExtension(routerkey);
routers.add(routerFactory.getRouter(url));
}
// append mock invoker selector
routers.add(new MockInvokersSelector());
Collections.sort(routers);
this.routers = routers;
}

public boolean isDestroyed() {
return destroyed;
}

public void destroy(){
destroyed = true;
}
//子类实现具体的获取invoker列表
protected abstract List<Invoker<T>> doList(Invocation invocation) throws RpcException ;

}

Directory具体的实现有两个RegistryDirectory注册目录服务和StaticDirectory静态目录服务。

RegistryDirectory

RegistryDirectory实现了NotifyListener接口,因此他本身也是一个监听器,可以在服务变更时接受通知,消费方要调用远程服务,会向注册中心订阅这个服务的所有的服务提供方,订阅的时候会调用notify方法,进行invoker实例的重新生成,也就是服务的重新引用。在服务提供方有变动时,也会调用notify方法,有关notify方法在Dubbo中订阅和通知解析那篇文章中已经解释,不做重复。subscribe方法也不做重复解释。

StaticDirectory

静态目录服务。

Dubbo中Directory解析的更多相关文章

  1. Dubbo中集群Cluster,负载均衡,容错,路由解析

    Dubbo中的Cluster可以将多个服务提供方伪装成一个提供方,具体也就是将Directory中的多个Invoker伪装成一个Invoker,在伪装的过程中包含了容错的处理,负载均衡的处理和路由的处 ...

  2. Dubbo中暴露服务的过程解析

    dubbo暴露服务有两种情况,一种是设置了延迟暴露(比如delay="5000"),另外一种是没有设置延迟暴露或者延迟设置为-1(delay="-1"): 设置 ...

  3. Dubbo中订阅和通知解析

    Dubbo中关于服务的订阅和通知主要发生在服务提供方暴露服务的过程和服务消费方初始化时候引用服务的过程中. 2345678910111213141516171819 public <T> ...

  4. Dubbo中编码和解码的解析

    (这里做的解析不是很详细,等到走完整个流程再来解析)Dubbo中编解码的工作由Codec2接口的实现来处理,回想一下第一次接触到Codec2相关的内容是在服务端暴露服务的时候,根据具体的协议去暴露服务 ...

  5. Dubbo中SPI扩展机制解析

    dubbo的SPI机制类似与Java的SPI,Java的SPI会一次性的实例化所有扩展点的实现,有点显得浪费资源. dubbo的扩展机制可以方便的获取某一个想要的扩展实现,每个实现都有自己的name, ...

  6. Dubbo中@Service工作过程解析

    Dubbo中@Service工作过程解析 Spring中的BeanPostProcessor 首先我们应当了解到在spring体系中BeanPostProcessor是什么.加载流程 它是什么 Bea ...

  7. Dubbo中服务消费者和服务提供者之间的请求和响应过程

    服务提供者初始化完成之后,对外暴露Exporter.服务消费者初始化完成之后,得到的是Proxy代理,方法调用的时候就是调用代理. 服务消费者经过初始化之后,得到的是一个动态代理类,InvokerIn ...

  8. dubbo源码解析五 --- 集群容错架构设计与原理分析

    欢迎来我的 Star Followers 后期后继续更新Dubbo别的文章 Dubbo 源码分析系列之一环境搭建 博客园 Dubbo 入门之二 --- 项目结构解析 博客园 Dubbo 源码分析系列之 ...

  9. 1、Dubbo源码解析--Dubbo如何驱动Spring IOC容器并配合工作的?

    首先Spring要注入自己的bean需要在Spring-provider.xml(提供者spring注入文件,名字可能不一样)添加bean注入,其中有dubbo的自定义标签,xml如何识别这些标签?拿 ...

随机推荐

  1. MySQL Join 的实现原理

    在寻找Join 语句的优化思路之前,我们首先要理解在MySQL 中是如何来实现Join 的,只要理解了实现原理之后,优化就比较简单了.下面我们先分析一下MySQL 中Join 的实现原理.在MySQL ...

  2. TopShelf安装多实例

    Topshelf 安装多实例命令: .\ConsoleApp1.exe -instance "newinstallname" install 多实例有一个好处就是容灾,当一个服务部 ...

  3. MySQL运维工具

    Mysql运维过程中设计的各类工具以及各个场景的的命令行的分类.大体总结如下的xmind图片(.xmind附件 加 Q1123654342). 大体上分为: 实例管理工具.高可用工具.慢日志查询工具. ...

  4. 百度AI技术QQ群

    百度语音QQ群 648968704 视频分析QQ群 632473158 DuerOSQQ群 604592023 图像识别QQ群 649285136 文字识别QQ群 631977213 理解与交互技术U ...

  5. mysql distinct field1,field2,field3, .... from table

    mysql distinct field1,field2,field3, .... from table 我们知道 这样的sql可以去掉重复项 (field1的重复项); select distinc ...

  6. .net core2.0添加json文件并转化成类注入控制器使用

    上一篇,我们介绍了如何读取自定义的json文件,数据是读取出来了,只是处理的时候太麻烦,需要一遍一遍写,很枯燥.那么有没有很好的办法呢?经过钻研,办法有了. 既然一个一个读取比较麻烦,那么可以把它放入 ...

  7. vfd电子时钟制作

    17年也没干个啥,年后就去折腾着玩意儿了,也不知道我折腾它还是它折腾我.反正总之现在勉强可以交作业了,呵呵 硬件: 1.罗耶振荡电路输出一路4v交流,一路25v交流 其中4v直接驱动灯丝,另一路经电桥 ...

  8. XGBoost算法--学习笔记

    学习背景 最近想要学习和实现一下XGBoost算法,原因是最近对项目有些想法,准备做个回归预测.作为当下比较火的回归预测算法,准备直接套用试试效果. 一.基础知识 (1)泰勒公式 泰勒公式是一个用函数 ...

  9. 同一台电脑上配置多个解压版tomcat方法(本例安装两个)

    一.在环境变量中设置变量() CATALINA_HOME = tomcat路径一 CATALINA_BASE = tomcat路径一 CATALINA_HOME2 = tomcat路径二 CATALI ...

  10. arcEngine开发之IMapControl接口

    简介 IMapControl接口最重要的是包含IMap属性,还提供另外的属性用于:管理一般的外观显示,管理图层,加载地图文档以及跟踪在界面上显示的图形. 小知识点:一般一个接口的最新实现是 Defau ...