根據配置文件請求服務端
網絡
查找服務端方式:直接查找、註冊中心查找
jvm
直接查找:在配置文件中直接配置服務端地址和實現接口 在沒有註冊中心,直連提供者的狀況下(例如:<dubbo:reference url="dubbo://service-host/com.foo.FooService?version=1.0.0" />),ReferenceConfig 解析出的 URL 的格式爲:dubbo://service-host/com.foo.FooService?version=1.0.0。 基於擴展點自適應機制,經過 URL 的 dubbo:// 協議頭識別,直接調用 DubboProtocol 的 refer() 方法,返回提供者引用。socket
註冊中心查詢:經過註冊中心找到服務端地址和實現接口 在有註冊中心,this
一、經過註冊中心發現提供者地址的狀況下 (例如:<dubbo:registry address="zookeeper://10.20.153.10:2181" />),ReferenceConfig 解析出的 URL 的格式爲: registry://registry-host/com.alibaba.dubbo.registry.RegistryService?refer=URL.encode("consumer://consumer-host/com.foo.FooService?version=1.0.0")。 二、基於擴展點自適應機制,經過 URL 的 registry:// 協議頭識別,就會調用 RegistryProtocol 的 refer() 方法,基於 refer 參數中的條件,查詢提供者 URL,如: dubbo://service-host/com.foo.FooService?version=1.0.0。 url
三、基於擴展點自適應機制,經過提供者 URL 的 dubbo:// 協議頭識別,就會調用 DubboProtocol 的 refer() 方法,獲得提供者引用。 而後 RegistryProtocol 將多個提供者引用,經過 Cluster 擴展點,假裝成單個提供者引用返回。
3d
客戶端消費過程:code
一、首先 ReferenceConfig 類的 init 方法調用 Protocol 的 refer 方法生成 Invoker 實例(如上圖中的紅色部分),這是服務消費的關鍵。cdn
二、接下來把 Invoker 轉換爲客戶端須要的接口(如:HelloWorld)。 關於每種協議如 RMI/Dubbo/Web service 等它們在調用 refer 方法生成 Invoker 實例:blog
Dubbo 的實現 Dubbo 協議的 Invoker 轉爲 Exporter 發生在 DubboProtocol 類的 export 方法,它主要是打開 socket 偵聽服務,並接收客戶端發來的各類請求,通信細節由 Dubbo 本身實現。 接口
RMI 的實現 RMI 協議的 Invoker 轉爲 Exporter 發生在 RmiProtocol類的 export 方法,它經過 Spring 或 Dubbo 或 JDK 來實現 RMI 服務,通信細節這一塊由 JDK 底層來實現,這就省了很多工做量。
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(DubboInvoker
、 HessianRpcInvoker
、 InjvmInvoker
、 RmiInvoker
、 WebServiceInvoker
中的任何一個),而該 Invoker 實現了真正的遠程服務調用。
服務提供者代碼:
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) throws RemoteException {
return "Hello " + name;
}
}
上面這個類會被封裝成爲一個 AbstractProxyInvoker 實例,並新生成一個 Exporter 實例。這樣當網絡通信層收到一個請求後,會找到對應的 Exporter 實例,並調用它所對應的 AbstractProxyInvoker 實例,從而真正調用了服務提供者的代碼。Dubbo 裏還有一些其餘的 Invoker 類,但上面兩種是最重要的。