dubbo protocol port 消费者端_Dubbo源码:搞定URL,就走完了进度条的一半
Dubbo 中的 URL
大家都知道,在互聯網領域,每個信息資源都有統一的且在網上唯一的地址,該地址就叫 URL(Uniform Resource Locator,統一資源定位符),它是互聯網的統一資源定位標志,也就是指網絡地址。
Dubbo 中任意的一個實現都可以抽象為一個 URL,Dubbo 使用 URL 來統一描述了所有對象和配置信息,并貫穿在整個 Dubbo 框架之中。
dubbo://172.17.32.91:20880/org.apache.dubbo.demo.DemoService?anyhost=true&application=dubbo-demo-api-provider&dubbo=2.0.2&interface=org.apache.dubbo.demo.DemoService&methods=sayHello,sayHelloAsync&pid=32508&release=&side=provider×tamp=1593253404714dubbo://172.17.32.91:20880/org.apache.dubbo.demo.DemoService?anyhost=true&application=dubbo-demo-api-provider&dubbo=2.0.2&interface=org.apache.dubbo.demo.DemoService&methods=sayHello,sayHelloAsync&pid=32508&release=&side=provider×tamp=1593253404714這個 Demo Provider 注冊到 ZooKeeper 上的 URL 信息,簡單解析一下這個 URL 的各個部分:
- protocol:dubbo 協議
- username/password:沒有用戶名和密碼
- host/port:172.17.32.91:20880
- path:org.apache.dubbo.demo.DemoService
- parameters:參數鍵值對,這里是問號后面的參數
下面是 URL 的構造方法:
public URL(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters, Map<String, Map<String, String>> methodParameters) { if (StringUtils.isEmpty(username) && StringUtils.isNotEmpty(password)) { throw new IllegalArgumentException("Invalid url"); } this.protocol = protocol; this.username = username; this.password = password; this.host = host; this.port = Math.max(port, 0); this.address = getAddress(this.host, this.port); while (path != null && path.startsWith("/")) { path = path.substring(1); } this.path = path; if (parameters == null) { parameters = new HashMap<>(); } else { parameters = new HashMap<>(parameters); } this.parameters = Collections.unmodifiableMap(parameters); this.methodParameters = Collections.unmodifiableMap(methodParameters); }另外,在 dubbo-common 包中還提供了 URL 的輔助類:
- URLBuilder, 輔助構造 URL
- URLStrParser, 將字符串解析成 URL 對象
URL 在 Dubbo 中被當作是“公共的契約”。一個 URL 可以包含非常多的擴展點參數,URL 作為上下文信息貫穿整個擴展點設計體系。
其實在 Dubbo 中使用 URL 的好處多多:
- 代碼更加易讀、易懂,不用花大量時間去揣測傳遞數據的格式和含義,進而形成一個統一的規范
- 作為方法的入參(相當于一個 Key/Value 都是 String 的 Map),含義比單個參數更豐富,當代碼需要擴展的時候,可以將新的參數以 Key/Value 的形式追加到 URL 之中,而不需要改變入參或是返回值的結構
- 可以省去很多溝通成本
URL 在 SPI 中的應用
Dubbo SPI 中有一個依賴 URL 的重要場景——適配器方法,是被 @Adaptive 注解標注的, URL 一個很重要的作用就是與 @Adaptive 注解一起選擇合適的擴展實現類。
例如,在 dubbo-registry-api 模塊中我們可以看到 RegistryFactory 這個接口,其中的 getRegistry() 方法上有 @Adaptive({"protocol"}) 注解,說明這是一個適配器方法,Dubbo 在運行時會為其動態生成相應的 “$Adaptive” 類型,如下所示:
public class RegistryFactory$Adaptive implements RegistryFactory { public Registry getRegistry(org.apache.dubbo.common.URL arg0) { if (arg0 == null) throw new IllegalArgumentException("..."); org.apache.dubbo.common.URL url = arg0; // 嘗試獲取URL的Protocol,如果Protocol為空,則使用默認值"dubbo" String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol()); if (extName == null) throw new IllegalStateException("..."); // 根據擴展名選擇相應的擴展實現,Dubbo SPI的核心原理在下一課時深入分析 RegistryFactory extension = (RegistryFactory) ExtensionLoader .getExtensionLoader(RegistryFactory.class) .getExtension(extName); return extension.getRegistry(arg0); } }我們會看到,在生成的 RegistryFactory$Adaptive 類中會自動實現 getRegistry() 方法,其中會根據 URL 的 Protocol 確定擴展名稱,從而確定使用的具體擴展實現類。
我們可以找到 RegistryProtocol 這個類,并在其 getRegistry() 方法中打一個斷點, 得到如下圖所示的內容:
這里傳入的 registryUrl 值為:
zookeeper://127.0.0.1:2181/org.apache.dubbo...那么在 RegistryFactory$Adaptive 中得到的擴展名稱為 zookeeper,此次使用的 Registry 擴展實現類就是 ZookeeperRegistryFactory。
URL 在服務暴露中的應用
Provider 在啟動時,會將自身暴露的服務注冊到 ZooKeeper 上,來看 ZookeeperRegistry.doRegister() 方法,在其中打個斷點,然后 Debug 啟動 Provider,會得到下圖:
傳入的 URL 中包含了 Provider 的地址(172.18.112.15:20880)、暴露的接口(org.apache.dubbo.demo.DemoService)等信息, toUrlPath() 方法會根據傳入的 URL 參數確定在 ZooKeeper 上創建的節點路徑,還會通過 URL 中的 dynamic 參數值確定創建的 ZNode 是臨時節點還是持久節點。
URL 在服務訂閱中的應用
Consumer 啟動后會向注冊中心進行訂閱操作,并監聽自己關注的 Provider。那 Consumer 是如何告訴注冊中心自己關注哪些 Provider 呢?
我們來看 ZookeeperRegistry 這個實現類,它是由上面的 ZookeeperRegistryFactory 工廠類創建的 Registry 接口實現,其中的 doSubscribe() 方法是訂閱操作的核心實現,在第 175 行打一個斷點,并 Debug 啟動 Demo 中 Consumer,會得到下圖所示的內容:
可以看到傳入的 URL 參數如下:
consumer://...?application=dubbo-demo-api-consumer&category=providers,configurators,routers&interface=org.apache.dubbo.demo.DemoService...其中 Protocol 為 consumer ,表示是 Consumer 的訂閱協議,其中的 category 參數表示要訂閱的分類,這里要訂閱 providers、configurators 以及 routers 三個分類;interface 參數表示訂閱哪個服務接口,這里要訂閱的是暴露 org.apache.dubbo.demo.DemoService 實現的 Provider。
通過 URL 中的上述參數,ZookeeperRegistry 會在 toCategoriesPath() 方法中將其整理成一個 ZooKeeper 路徑,然后調用 zkClient 在其上添加監聽。
本文轉自公眾號:勾勾的Java宇宙
歡迎大家來留言互動哦!
總結
以上是生活随笔為你收集整理的dubbo protocol port 消费者端_Dubbo源码:搞定URL,就走完了进度条的一半的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql --force -f_Mys
- 下一篇: mysql主从修改系统参数步骤_mysq