dubbo 支持的9種協議


 

 

轉:

dubbo 支持的9種協議

 

 

 

文章目錄

    一、9種協議
        1、dubbo 協議 (默認)
        2、rmi 協議
        3、hessian 協議
        4、http 協議
        5、webservice 協議
        6、thrift 協議
        7、memcached 協議
        8、redis 協議
        9、rest ( 就是 RestFull)
    二、多協議配置
        不同服務使用不同協議
        同時使用多種協議
    三、面試題:

Dubbo支持dubbo、rmi、hessian、http、webservice、thrift、redis等多種協議,但是Dubbo官網是推薦我們使用Dubbo協議的。

下面我們就針對Dubbo的每種協議詳解講解,以便我們在實際應用中能夠正確取舍。
一、9種協議
1、dubbo 協議 (默認)

1、dubbo 缺省協議 采用單一長連接和NIO異步通訊,適合於小數據量大並發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的情況
2、不適合傳送大數據量的服務,比如傳文件,傳視頻等,除非請求量很低。

缺省協議,使用基於mina1.1.7+hessian3.2.1的tbremoting交互。

特性

    連接個數:單連接
    連接方式:長連接
    傳輸協議:TCP
    傳輸方式:NIO異步傳輸
    序列化:Hessian 二進制序列化
    適用范圍:傳入傳出參數數據包較小(建議小於100K),消費者比提供者個數多,單一消費者無法壓滿提供者,盡量不要用dubbo協議傳輸大文件或超大字符串。
    適用場景:常規遠程服務方法調用

配置

<!--配置協議: -->
<dubbo:protocol name="dubbo" port="20880" />

<!--設置默認協議: -->
<dubbo:provider protocol="dubbo" />

<!-- 設置服務協議: -->
<dubbo:service protocol="dubbo" />

<!-- 多端口 -->
<dubbo:protocol id="dubbo1" name="dubbo" port="20880" />
<dubbo:protocol id="dubbo2" name="dubbo" port="20881" />

<!-- 配置協議選項: -->
<dubbo:protocol name=“dubbo” port=“9090” server=“netty” client=“netty” codec=“dubbo”
                serialization=“hessian2” charset=“UTF-8” threadpool=“fixed” threads=“100”
                 queues=“0” iothreads=“9” buffer=“8192” accepts=“1000” payload=“8388608” />

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

3、Dubbo協議缺省每服務每提供者每消費者使用單一長連接,如果數據量較大,可以使用多個連接。

<dubbo:protocol name="dubbo" connections="2" />

    1

<dubbo:service connections=”0”>或<dubbo:reference connections=”0”>表示該服務使用JVM共享長連接。(缺省)
<dubbo:service connections=”1”>或<dubbo:reference connections=”1”>表示該服務使用獨立長連接。
<dubbo:service connections=”2”>或<dubbo:reference connections=”2”>表示該服務使用獨立兩條長連接。

4、為防止被大量連接撐掛,可在服務提供方限制大接收連接數,以實現服務提供方自我保護

<dubbo:protocol name="dubbo" accepts="1000" />

    1

常見問題

為什么要消費者比提供者個數多?
因dubbo協議采用單一長連接,假設網絡為千兆網卡(1024Mbit=128MByte),根據測試經驗數據每條連接最多只能壓滿7MByte(不同的環境可能不一樣,供參考),理論上1個服務提供者需要20個服務消費者才能壓滿網卡

為什么不能傳大包?
因dubbo協議采用單一長連接,如果每次請求的數據包大小為500KByte,假設網絡為千兆網卡(1024Mbit=128MByte),每條連接最大7MByte(不同的環境可能不一樣,供參考),單個服務提供者的TPS(每秒處理事務數)最大為:128MByte / 500KByte = 262。單個消費者調用單個服務提供者的TPS(每秒處理事務數)最大為:7MByte / 500KByte = 14。如果能接受,可以考慮使用,否則網絡將成為瓶頸。

為什么采用異步單一長連接?
因為服務的現狀大都是服務提供者少,通常只有幾台機器,而服務的消費者多,可能整個網站都在訪問該服務,比如Morgan的提供者只有6台提供者,卻有上百台消費者,每天有1.5億次調用,如果采用常規的hessian服務,服務提供者很容易就被壓跨,通過單一連接,保證單一消費者不會壓死提供者,長連接,減少連接握手驗證等,並使用異步IO,復用線程池,防止C10K問題。

接口增加方法,對客戶端無影響,如果該方法不是客戶端需要的,客戶端不需要重新部署;
輸入參數和結果集中增加屬性,對客戶端無影響,如果客戶端並不需要新屬性,不用重新
部署;

輸入參數和結果集屬性名變化,對客戶端序列化無影響,但是如果客戶端不重新部署,不管輸入還是輸出,屬性名變化的屬性值是獲取不到的。

總結:服務器端 和 客戶端 對 領域對象 並不需要完全一致,而是按照最大匹配原則。

如果不是集成Spring,單獨配置如下:

dubbo.service.protocol=dubbo

    1

2、rmi 協議

1、RMI協議采用JDK標准的java.rmi.*實現,采用阻塞式短連接和JDK標准序列化方式 。

注:
如果正在使用RMI提供服務給外部訪問(公司內網環境應該不會有攻擊風險),同時應用里依賴了老的common-collections包(dubbo不會依賴這個包,請排查自己的應用有沒有使用)的情況下,存在反序列化安全風險。
請檢查應用:
將commons-collections3 請升級到3.2.2版本:
https://commons.apache.org/proper/commons-collections/release_3_2_2.html

將commons-collections4 請升級到4.1版本:
https://commons.apache.org/proper/commons-collections/release_4_1.html

新版本的commons-collections解決了該問題 。

特性

    連接個數:多連接
    連接方式:短連接
    傳輸協議:TCP
    傳輸方式:同步傳輸
    序列化:Java標准二進制序列化
    適用范圍:傳入傳出參數數據包大小混合,消費者與提供者個數差不多,可傳文件。
    適用場景:常規遠程服務方法調用,與原生RMI服務互操作

接口
如果服務接口繼承了java.rmi.Remote接口,可以和原生RMI互操作,即:
提供者用Dubbo的RMI協議暴露服務,消費者直接用標准RMI接口調用,或者提供方用標准RMI暴露服務,消費方用Dubbo的RMI協議調用。

如果服務接口沒有繼承java.rmi.Remote接口,缺省Dubbo將自動生成一個com.xxx.XxxService$Remote的接口,並繼承java.rmi.Remote接口,並以此接口暴露服務,

但如果設置了<dubbo:protocol name="rmi" codec="spring" />,將不生成$Remote接口,而使用Spring的RmiInvocationHandler接口暴露服務,和Spring兼容。

配置

<!-- 定義 RMI 協議: -->
<dubbo:protocol name="rmi" port="1099" />

<!--設置默認協議: -->
<dubbo:provider protocol="rmi" />

<!-- 設置服務協議: -->
<dubbo:service protocol="rmi" />

<!--多端口: -->
<dubbo:protocol id="rmi1" name="rmi" port="1099" />
<dubbo:protocol id="rmi2" name="rmi" port="2099" />
<dubbo:service protocol="rmi1" />

<!--Spring 兼容性:-->
<dubbo:protocol name="rmi" codec="spring" />

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

3、hessian 協議

Hessian 協議用於集成 Hessian 的服務,Hessian 底層采用 Http 通訊,采用 Servlet 暴露服務,Dubbo 缺省內嵌 Jetty 作為服務器實現。

Dubbo 的 Hessian 協議可以和原生 Hessian 服務互操作,即:

    提供者用 Dubbo 的 Hessian 協議暴露服務,消費者直接用標准 Hessian 接口調用
    或者提供方用標准 Hessian 暴露服務,消費方用 Dubbo 的 Hessian 協議調用。

Hessian 是 Caucho 開源的一個 RPC 框架,其通訊效率高於 WebService 和 Java 自帶的序列化。

特性

    連接個數:多連接
    連接方式:短連接
    傳輸協議:HTTP
    傳輸方式:同步傳輸
    序列化:Hessian二進制序列化
    適用范圍:傳入傳出參數數據包較大,提供者比消費者個數多,提供者壓力較大,可傳文件。
    適用場景:頁面傳輸,文件傳輸,或與原生hessian服務互操作

依賴:

<dependency>
    <groupId>com.caucho</groupId>
    <artifactId>hessian</artifactId>
    <version>4.0.7</version>
</dependency>

    1
    2
    3
    4
    5

約束
1、參數及返回值需實現Serializable接口
2、參數及返回值不能自定義實現List, Map, Number, Date, Calendar等接口,只能用JDK自帶的實現,因為hessian會做特殊處理,自定義實現類中的屬性值都會丟失。

配置

<!-- 定義 hessian 協議: -->
<dubbo:protocol name="hessian" port="8080" server="jetty" />

<!--設置默認協議: -->
<dubbo:provider protocol="hessian" />

<!-- 設置 service 協議: -->
<dubbo:service protocol="hessian" />

<!-- 多端口:-->
<dubbo:protocol id="hessian1" name="hessian" port="8080" />
<dubbo:protocol id="hessian2" name="hessian" port="8081" />

<!--直連:-->
<dubbo:reference id="helloService" interface="HelloWorld" url="hessian://10.20.153.10:8080/helloWorld" />

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

web.xml 配置:

<servlet>
     <servlet-name>dubbo</servlet-name>
     <servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
     <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
     <servlet-name>dubbo</servlet-name>
     <url-pattern>/*</url-pattern>
</servlet-mapping>

    1
    2
    3
    4
    5
    6
    7
    8
    9

注意:如果使用servlet派發請求
協議的端口<dubbo:protocol port="8080" />必須與servlet容器的端口相同,
協議的上下文路徑<dubbo:protocol contextpath="foo" />必須與servlet應用的上下文路徑相同。
4、http 協議

基於http表單的遠程調用協議。參見:[HTTP協議使用說明]

特性

    連接個數:多連接
    連接方式:短連接
    傳輸協議:HTTP
    傳輸方式:同步傳輸
    序列化:表單序列化 ,即 json
    適用范圍:傳入傳出參數數據包大小混合,提供者比消費者個數多,可用瀏覽器查看,可用表單或URL傳入參數,暫不支持傳文件。
    適用場景:需同時給應用程序和瀏覽器JS使用的服務。

配置

<!-- 配置協議:-->
<dubbo:protocol   name="http"  port="8080" />

<!-- 配置 Jetty Server (默認):-->
<dubbo:protocol ...  server="jetty" />

<!-- 配置 Servlet Bridge Server (推薦使用): -->
<dubbo:protocol ... server="servlet" />

    1
    2
    3
    4
    5
    6
    7
    8

配置 DispatcherServlet:

<servlet>
         <servlet-name>dubbo</servlet-name>
         <servlet-class>org.apache.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
         <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
         <servlet-name>dubbo</servlet-name>
         <url-pattern>/*</url-pattern>
</servlet-mapping>

    1
    2
    3
    4
    5
    6
    7
    8
    9

注意:如果使用 servlet 派發請求 :

    協議的端口<dubbo:protocol port="8080" />必須與servlet容器的端口相同,
    協議的上下文路徑<dubbo:protocol contextpath="foo" />必須與servlet應用的上下文路徑相同。

5、webservice 協議

基於 WebService 的遠程調用協議,基於 Apache CXF的 frontend-simple 和 transports-http 實現。

可以和原生 WebService 服務互操作,即:

    提供者用 Dubbo 的 WebService 協議暴露服務,消費者直接用標准 WebService 接口調用,
    或者提供方用標准 WebService 暴露服務,消費方用 Dubbo 的 WebService 協議調用。

依賴

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-simple</artifactId>
    <version>2.6.1</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>2.6.1</version>
</dependency>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

特性

    連接個數:多連接
    連接方式:短連接
    傳輸協議:HTTP
    傳輸方式:同步傳輸
    序列化:SOAP文本序列化
    適用場景:系統集成,跨語言調用

1、基於CXF的 frontend-simple 和 transports-http 實現。
2、CXF是Apache開源的一個RPC框架:http://cxf.apache.org,由Xfire和Celtix合並而來 。

可以和原生WebService服務互操作,即:
提供者用Dubbo的WebService協議暴露服務,消費者直接用標准WebService接口調用,或者提供方用標准WebService暴露服務,消費方用Dubbo的WebService協議調用。

約束
參數及返回值需實現Serializable接口
參數盡量使用基本類型和POJO。

配置

<!-- 配置協議: -->
<dubbo:protocol name="webservice" port="8080" server="jetty" />

<!-- 配置默認協議:-->
<dubbo:provider protocol="webservice" />

<!-- 配置服務協議:-->
<dubbo:service protocol="webservice" />

<!--多端口: -->
<dubbo:protocol id="webservice1" name="webservice" port="8080" />
<dubbo:protocol id="webservice2" name="webservice" port="8081" />

<!-- 直連: -->
<dubbo:reference id="helloService" interface="HelloWorld" url="webservice://10.20.153.10:8080/com.foo.HelloWorld" />

<!-- WSDL -->
http://10.20.153.10:8080/com.foo.HelloWorld?wsdl

<!-- Jetty Server: (默認) -->
<dubbo:protocol ... server="jetty" />

<!-- Servlet Bridge Server: (推薦) -->
<dubbo:protocol ... server="servlet" />

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

配置 DispatcherServlet:

<servlet>
     <servlet-name>dubbo</servlet-name>
     <servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
     <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
     <servlet-name>dubbo</servlet-name>
     <url-pattern>/*</url-pattern>
</servlet-mapping>

    1
    2
    3
    4
    5
    6
    7
    8
    9

注意:如果使用servlet派發請求:
協議的端口<dubbo:protocol port=“8080” />必須與servlet容器的端口相同,
協議的上下文路徑<dubbo:protocol contextpath=“foo” />必須與servlet應用的上下文路徑相同。
6、thrift 協議

當前 dubbo 支持的 thrift 協議是對 thrift 原生協議 [2] 的擴展,在原生協議的基礎上添加了一些額外的頭信息,比如 service name,magic number 等。

使用 dubbo thrift 協議同樣需要使用 thrift 的 idl compiler 編譯生成相應的 java 代碼,后續版本中會在這方面做一些增強。

依賴

<dependency>
    <groupId>org.apache.thrift</groupId>
    <artifactId>libthrift</artifactId>
    <version>0.8.0</version>
</dependency>

    1
    2
    3
    4
    5

配置

<dubbo:protocol name="thrift" port="3030" />

    1

常見問題
Thrift不支持null值,不能在協議中傳null
7、memcached 協議

基於 memcached實現的 RPC 協議。

注冊 memcached 服務的地址

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("memcached://10.20.153.11/com.foo.BarService?category=providers&dynamic=false&application=foo&group=member&loadbalance=consistenthash"));

    1
    2
    3

在客戶端引用

在客戶端使用 :

<dubbo:reference id="cache"
            interface="http://10.20.160.198/wiki/display/dubbo/java.util.Map" group="member" />

    1
    2

或者點對點直連:

<dubbo:reference id="cache"
            interface="http://10.20.160.198/wiki/display/dubbo/java.util.Map"
            url="memcached://10.20.153.10:11211" />

    1
    2
    3

自定義接口:

<dubbo:reference id="cache"
            interface="com.foo.CacheService" url="memcached://10.20.153.10:11211" />

    1
    2

方法名建議和memcached的標准方法名相同,即:get(key), set(key, value), delete(key)。

如果方法名和memcached的標准方法名不相同,則需要配置映射關系:(其中”p:xxx”為spring的標准p標簽)

<dubbo:reference id="cache" interface="com.foo.CacheService"
                url="memcached://10.20.153.10:11211" p:set="putFoo"
                p:get="getFoo" p:delete="removeFoo" />

    1
    2
    3

8、redis 協議

基於 Redis實現的 RPC 協議。

注冊 redis 服務的地址

可以通過腳本或監控中心手工填寫表單注冊redis服務的地址:

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("redis://10.20.153.11/com.foo.BarService?category=providers&dynamic=false&application=foo&group=member&loadbalance=consistenthash"));

    1
    2
    3

在客戶端引用

在客戶端使用:

<dubbo:reference id="store"
            interface="http://10.20.160.198/wiki/display/dubbo/java.util.Map" group="member" />

    1
    2

或者,點對點直連:

<dubbo:reference id="store"  interface="http://10.20.160.198/wiki/display/dubbo/java.util.Map"
    url="redis://10.20.153.10:6379" />

    1
    2

也可以使用自定義接口:

<dubbo:reference id="store" interface="com.foo.StoreService" url="redis://10.20.153.10:6379" />

    1

方法名建議和redis的標准方法名相同,即:get(key), set(key, value), delete(key)。

如果方法名和redis的標准方法名不相同,則需要配置映射關系:(其中”p:xxx”為spring的標准p標簽)

<dubbo:reference id="cache" interface="com.foo.CacheService"
            url="memcached://10.20.153.10:11211"
             p:set="putFoo" p:get="getFoo" p:delete="removeFoo" />

    1
    2
    3

9、rest ( 就是 RestFull)

基於標准的Java REST API——JAX-RS 2.0(Java API for RESTful Web Services的簡寫)實現的REST調用支持

參考: http://dubbo.apache.org/zh-cn/docs/user/references/protocol/rest.html
二、多協議配置

Dubbo 允許配置多協議,在不同服務上支持不同協議或者同一服務上同時支持多種協議。
不同服務使用不同協議

不同服務在性能上適用不同協議進行傳輸,比如大數據用短連接協議,小數據大並發用長連接協議

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
    <dubbo:application name="world"  />
    <dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" />
    
    <!-- 多協議配置 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <dubbo:protocol name="rmi" port="1099" />
    
    <!-- 指定使用 dubbo協議 -->
    <dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" protocol="dubbo" />
    
    <!-- 指定使用 rmi協議 -->
    <dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" protocol="rmi" />
    
</beans>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

同時使用多種協議

需要與 http 客戶端互操作

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
    <dubbo:application name="world"  />
    <dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" />
    
    <!-- 多協議配置 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <dubbo:protocol name="hessian" port="8080" />
    
    <!-- 使用多個協議暴露服務 -->
    <dubbo:service id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" protocol="dubbo,hessian" />
    
</beans>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

三、面試題:

1、dubbo推薦用什么協議?
默認使用 dubbo 協議。

2、dubbo 默認使用什么序列化框架,你知道的還有哪些?
dubbo 有多種協議,不同的協議默認使用不同的序列化框架。比如:

dubbo 協議 默認使用 Hessian2 序列化。(說明:Hessian2 是阿里在 Hessian 基礎上進行的二次開發,起名為Hessian2 )
rmi協議 默認為 java 原生序列化,
http 協議 默認為 為 json 。

此外補充,
hessian 協議,默認是 hessian 序列化;
webservice 協議,默認是 soap 文本序列化 。

上面說的是默認使用序列化。也可以使用第三方的序列化框架,如 Kryo 、 FST等序列化框架,詳情參考:
https://blog.csdn.net/xiaojin21cen/article/details/90269659
https://blog.csdn.net/xiaojin21cen/article/details/90269952

知識來源:

上面的回答在dubbo 官方文檔中有說明 。 http://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-protocol.html
在這里插入圖片描述

在這里插入圖片描述

如上圖所示,在 serialization 這一行中,如果使用的是dubbo協議,則默認 序列化 框架是 hessian2,
rmi協議,則默認為 java ;http 協議,則默認為 為json 。
---------------------
版權聲明:本文為CSDN博主「xiaojin21cen」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/xiaojin21cen/article/details/79834222


免責聲明!

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



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