Dubbo中Directory解析

Directory表明多個Invoker,能夠把它當作List ,但與List不一樣的是,它的值多是動態變化的,好比註冊中心推送變動。Cluster將Directory中的多個Invoker假裝成一個Invoker,對上層透明,假裝過程包含了容錯邏輯,調用失敗後,重試另外一個。

上面是文檔上對Directory的解釋。
web

Directory接口

Directory接口繼承了Node接口:app

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:this

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靜態目錄服務。url

RegistryDirectory

RegistryDirectory實現了NotifyListener接口,所以他自己也是一個監聽器,能夠在服務變動時接受通知,消費方要調用遠程服務,會向註冊中心訂閱這個服務的全部的服務提供方,訂閱的時候會調用notify方法,進行invoker實例的從新生成,也就是服務的從新引用。在服務提供方有變更時,也會調用notify方法,有關notify方法在Dubbo中訂閱和通知解析那篇文章中已經解釋,不作重複。subscribe方法也不作重複解釋。spa

StaticDirectory

靜態目錄服務。日誌

相關文章
相關標籤/搜索