Dubbo(六):Dubbo中的URL統一資源模型與Dubbo協議


一、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&timestamp=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&timestamp=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起到了很大的作用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM