dubbo用在微服務,那麼肯定是需要使用到集群的 ,面對集群就需要處理機器宕機的問題,如果是普通服務,乙個機子宕機,那麼我們還可以人工去維護,在集群裡面宕機,就很麻煩,所以需要我們軟體有容錯的功能,dubbo在容錯機制,分為四個
1.服務目錄 directory(也就是本章)
2.服務路由router
3.集群cluster
4.負責均衡loadbalance
對於服務目錄是什麼?
它儲存了服務提供者的資訊,比如ip,port等等,它需要有效性,也就是需要動態的更新,我們的服務提供者把自己註冊到zk上面,消費者就會到zk上拉取,為每提供者生成乙個invoker物件,儲存起來。也正是因為有服務目錄的存在,所以當zk掛掉的時候,dubbo還能繼續根據服務目錄的資訊,進行通訊。
我們的類其實很簡單,分為staticdirectory和registrydirectory,他們共同的父類abstractdirectory
1.abstracdirectory類
核心方法,列舉invoker,比較簡單,其實也就是遍歷一下
public abstract class abstractdirectoryimplements directory
...}
我們看一下routerchain,路由鏈,
public class routerchain
2.staticdirectory靜態服務目錄,記憶體存放的invoker是不會發生改變的,它有乙個唯一字段
private final list> invokers;
然後就是父類定義的抽象方法實現dolist()
protected list> dolist(invocation invocation) throws rpcexception catch (throwable t)
} return finalinvokers == null ? collections.emptylist() : finalinvokers;
}
3.registrydirectory是一種動態服務目錄,實現了notifylistener介面,當註冊中心服務配置發生變化之後,registrydirectory可收到與當前服務相關的變化,然後重新整理到invoker list中。重要的邏輯三個:invoker列舉,接收服務配置更新,invoker重新整理。
這個類的內容,明顯就比staticdirectory複雜多了,它的字段,方法量很大,而且還有三個內部類。其方法主要還是實現上面說的三個邏輯。
3.1.invoker列舉
public list> dolist(invocation invocation)
if (multigroup)
//直接從父類中獲取
list> invokers = null;
try
return invokers == null ? collections.emptylist() : invokers;
}
3.2.接收服務配置更新
public synchronized void notify(listurls)
}//重新整理invoker 列表
refreshoverrideandinvoker(providerurls); //【入】
}
3.3.invoker重新整理
private void refreshoverrideandinvoker(listurls)
private void refreshinvoker(listinvokerurls) else
if (invokerurls.isempty() && this.cachedinvokerurls != null) else
if (invokerurls.isempty())
//1.將url 轉換成 invoker 【分析 入】
map> newurlinvokermap = toinvokers(invokerurls);// translate url list to invoker map
//轉換出錯,直接列印異常返回
if (collectionutils.isemptymap(newurlinvokermap))
//將newurlinvoker 轉成方法名到invoker列表 的對映
list> newinvokers = collections.unmodifiablelist(new arraylist<>(newurlinvokermap.values()));
// pre-route and build cache, notice that route cache should build on original invoker list.
routerchain.setinvokers(newinvokers);
//2.合併多個組的invoker 【分析 入】
this.invokers = multigroup ? tomergeinvokerlist(newinvokers) : newinvokers;
this.urlinvokermap = newurlinvokermap;
try catch (exception e) }}
3.3.1 url轉invoker
//將 urls 轉換成為 invoker
private map> toinvokers(listurls)
setkeys = new hashset<>();
//獲取 服務消費端配置的 協議
string queryprotocols = this.querymap.get(protocol_key);
for (url providerurl : urls)
}if (!accept)
}//忽略 empty 協議
if (empty_protocol.equals(providerurl.getprotocol())) //通過 spi 檢測服務端協議是否被消費端支援,不支援則丟擲異常
....
//合併url
url url = mergeurl(providerurl);
string key = url.tofullstring(); // the parameter urls are sorted
if (keys.contains(key))
keys.add(key);
// 將本地緩衝invoker 緩衝賦值給localurlinvokermap
map> localurlinvokermap = this.urlinvokermap; // local reference
//獲取與url 對應的invoker
invokerinvoker = localurlinvokermap == null ? null : localurlinvokermap.get(key);
if (invoker == null) else
if (enabled)
} catch (throwable t)
if (invoker != null)
} else
}keys.clear();
return newurlinvokermap;
}
3.3.2 合併invoker
private list> tomergeinvokerlist(list> invokers)
if (groupmap.size() == 1) else if (groupmap.size() > 1)
} else
return mergedinvokers;
}
3.3.3 摧毀無用invoker
private void destroyunusedinvokers(map> oldurlinvokermap, map> newurlinvokermap)
// check deleted invoker
listdeleted = null;
if (oldurlinvokermap != null) //如果不包含,則把老的invoker 放到deleted列表中
deleted.add(entry.getkey());}}
}if (deleted != null)
} catch (exception e) }}}}}
Dubbo原始碼閱讀 三 Dubbo 服務註冊
通過註解來註冊dubbo服務的時候,在服務端和消費端都需要用到乙個元件dubbocomponentscanregistrar,先看下registerbeandefinitions 方法 public void registerbeandefinitions annotationmetadata im...
Dubbo服務註冊原始碼分析
服務在本地發布完成,那麼接下去要進入服務的註冊階段 final registry registry getregistry origininvoker final url registeredproviderurl geturltoregistry providerurl,registryurl d...
Dubbo原始碼解析 服務暴露原理
服務發布和服務的引用到底什麼實現的呢?我們追蹤這個問題進行下面的學習?首先我們通過控制台檢視服務啟動過程中,日誌記錄了什麼?通過日誌看出發布的過程 暴露本地服務 暴露遠端服務 啟動netty 連線zookeeper 註冊到zookeeper 監聽zookeeper the service ready...