Dubbo(五):Dubbo中的URL統一資源模型與Dubbo協議
阿新 • • 發佈:2020-02-16
一、URL簡介
URL也就是Uniform Resource Locator,中文叫統一資源定位符。Dubbo中無論是服務消費方,或者服務提供方,或者註冊中心。都是通過URL進行定位資源的。所以今天來聊聊Dubbo中的統一URL資源模型是怎麼樣的。
二、Dubbo中的URL
標準的URL格式如下:
protocol://username:password@host:port/path?key=value&key=value
在Dubbo中URL也是主要由上面的引數組成。
1 public URL(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters) { 2 if ((username == null || username.length() == 0) 3 && password != null && password.length() > 0) { 4 throw new IllegalArgumentException("Invalid url, password without username!"); 5 } 6 this.protocol = protocol; 7 this.username = username; 8 this.password = password; 9 this.host = host; 10 this.port = (port < 0 ? 0 : port); 11 this.path = path; 12 // trim the beginning "/" 13 while(path != null && path.startsWith("/")) { 14 path = path.substring(1); 15 } 16 if (parameters == null) { 17 parameters = new HashMap<String, String>(); 18 } else { 19 parameters = new HashMap<String, String>(parameters); 20 } 21 this.parameters = Collections.unmodifiableMap(parameters); 22 }
可以從上面原始碼看出:
-
- protocol:一般是 dubbo 中的各種協議 如:dubbo、thrift、http、zk
- username/password:使用者名稱/密碼
- host/port:主機IP地址/埠號
- path:介面名稱
- parameter:引數鍵值對
大致樣子如下:
dubbo://192.168.1.6:20880/moe.cnkirito.sample.HelloService?timeout=3000 描述一個 dubbo 協議的服務 zookeeper://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.2&interface=org.apache.dubbo.registry.RegistryService&pid=1214&qos.port=33333×tamp=1545721981946 描述一個 zookeeper 註冊中心 consumer://30.5.120.217/org.apache.dubbo.demo.DemoService?application=demo-consumer&category=consumers&check=false&dubbo=2.0.2&interface=org.apache.dubbo.demo.DemoService&methods=sayHello&pid=1209&qos.port=33333&side=consumer×tamp=1545721827784 描述一個消費者
三、Dubbo中有關URL的服務
1、解析服務
-
- Spring在遇到dubbo名稱空間時,會回撥DubboNamespaceHandler。這個類也是Dubbo基於spring擴充套件點編寫的解析xml檔案的類。
- 解析的xml標籤使用DubboBeanDefinitionParser將其轉化為bean物件。
- 服務提供方在ServiceConfig.export()初始化時將bean物件轉化為URL格式,所有Bean屬性轉換成URL引數。這時候的URL就會傳給協議擴充套件點。根據URL中protocol的值通過擴充套件點自適應機制進行不同協議的服務暴露或引用。
- 而服務消費方則是ReferenceConfig.export()方法。
2、直接暴露服務埠
-
- 在沒有註冊中心時,ServiceConfig解析出的URL格式為:dubbo://service-host/com.foo.FooService?version=1.0.0
- 基於擴充套件點自適應機制。通過URL的dubbo://協議頭識別,這時候就呼叫DubboProtocol中的export方法進行暴露服務埠
3、向註冊中心暴露服務埠
-
- 有註冊中心時。ServiceConfig解析出的URL格式就類似:registry://registry-host/org.apache.dubbo.registry.RegistryService?export=URL.encode("dubbo://service-host/com.foo.FooService?version=1.0.0")
- 基於擴充套件點自適應機制,識別到URL以registry://開頭,就會呼叫RegistryProtocol中的export方法先將該URL註冊到註冊中心裡
- 再傳給Protocol擴充套件點進行暴露,這時候就只剩下dubbo://service-host/com.foo.FooService?version=1.0.0。同樣的基於dubbo://協議頭識別,通過DubboProtocol的export方法開啟服務埠
4、直接引用服務
-
- 在沒有註冊中心,ReferenceConfig解析出的URL格式就為dubbo://service-host/com.foo.FooService?version=1.0.0
- 基於擴充套件點自適應機制,通過 URL 的dubbo://協議頭識別,直接呼叫DubboProtocol的refer方法,返回提供者引用
5、從註冊中心引用服務
-
- 有註冊中心時,ReferenceCofig解析出來的URL格式為:registry://registry-host/org.apache.dubbo.registry.RegistryService?refer=URL.encode("consumer://consumer-host/com.foo.FooService?version=1.0.0")
- 同樣先識別URL的協議頭,呼叫RegistryProtocol中的refer方法
- 通過refer引數中的條件查詢到提供者的URL。如dubbo://service-host/com.foo.FooService?version=1.0.0。此時就會呼叫DubboProtocol中的refer方法得到提供者引用
- 最後若是存在叢集Cluster擴充套件點,需要偽裝成單個提供者引用返回
四、Dubbo協議
1、協議簡介
聊完了Dubbo中的URL模型就來聊聊Dubbo中的協議。協議是雙方確定的交流語義,協議在雙方傳輸資料中起到的了交換作用,沒有協議就無法完成資料交換。在dubbo中就是Codec2
@SPI public interface Codec2 { @Adaptive({Constants.CODEC_KEY}) void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException; @Adaptive({Constants.CODEC_KEY}) Object decode(Channel channel, ChannelBuffer buffer) throws IOException; enum DecodeResult { NEED_MORE_INPUT, SKIP_SOME_INPUT } }
encode是將通訊物件編碼到ByteBufferWrapper,decode是將從網路上讀取的ChannelBuffer解碼為Object。
2、協議圖解
具體的解釋如下:
- Magic High&Magic Low(16bits):標識協議的版本號,Dubbo協議:0xdabb
- Req/Res(1bit):1代表請求,0代表響應
- 2Way(1bit)僅在Req/Res為1時才有用(也就是請求),標識是否期望從伺服器返回值。如果需要則為1.
- Event(1bit)標識是否是事件訊息。比如:如果是心跳時間則設定為1
- Serialization ID(5bits):標識序列化型別。 Status(8bits):僅在Req/Res為0時才有用(即響應)。主要用於標識響應狀態
- 20:OK,響應正確
- 30:CLIENT_TIMEOUT,客戶端連線超時
- 31:SERVER_TIMEOUT,服務端連線超時
- 40:BAD_REQUEST,錯誤請求
- 50:BAD_RESPONSE,錯誤響應
- 60:SERVICE_NOT_FOUND,服務未找到
- 70:SERVICE_ERROR,服務出錯
- 80:SERVER_ERROR,服務端出錯
- 90:CLIENT_ERROR,客戶端出錯
- 100:SERVER_THREADPOOL_EXHAUSTED_ERROR,服務端執行緒池已滿,無法建立新執行緒
- Request ID(64bits):標識唯一請求,long型別
- Data Length(32bits):序列化後的內容長度(可變的),int型別。這也是為什麼實體類需要實現序列化介面。因為Dubbo協議底層是傳輸序列化後的內容
- Variable Part:被特定的序列化型別序列化後,每個部分都是一個byte[]或byte
- 如果是請求包,則每個部分依次為:Dubbo Version、Service name、Service version、Method name、Method Parameter types、Method arguments、Attachments
- 如果是響應包,則每個部分依次為:返回值型別(0表示異常,1是正常響應,2是返回空值)、返回值。
五、總結
到這裡就稍微解釋了一下Dubbo內部的URL以及Dubbo的協議欄位。可以說這兩個對我們瞭解Dubbo起到了很大的作