1. 程式人生 > >Dubbo服務 上傳檔案解決方案以及Hessian協議

Dubbo服務 上傳檔案解決方案以及Hessian協議

協議支援

Dubbo支援多種協議,如下所示:

  • Dubbo協議
  • Hessian協議
  • HTTP協議
  • RMI協議
  • WebService協議
  • Thrift協議
  • Memcached協議
  • Redis協議

在通訊過程中,不同的服務等級一般對應著不同的服務質量,那麼選擇合適的協議便是一件非常重要的事情。你可以根據你應用的建立來選擇。例如,使用RMI協議,一般會受到防火牆的限制,所以對於外部與內部進行通訊的場景,就不要使用RMI協議,而是基於HTTP協議或者Hessian協議。

dubbo服務不支援File檔案型別的引數,遠端呼叫是這樣的:介面呼叫實際就是資料的傳送過程,File 這樣的型別是不能夠序列化的,因為File 不是資料,只是一個磁碟檔案的抽象。

解決方案:

  • 使用hessian協議進行傳輸 (參照dubbo 官網,或者搜尋dubbo hessian )
  • 將檔案轉換成byte[]繼續使用dubbo協議(這種情況一般用於上傳檔案跟業務有關聯)

我們這裡使用hessian協議進行傳輸(當然也可以轉換成byte[]繼續使用dubbo協議)

下面是需要進行的配置

customer

需要引入hessian的包

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

provider

pom.xml 需要引入 hessian,jetty的包(Hessian底層採用Http通訊,採用Servlet暴露服務,Dubbo預設內嵌Jetty作為伺服器實現)

<dependency>
    <groupId>com.caucho</groupId>
    <artifactId>hessian</artifactId>
    <version>4.0.7</version>
</dependency>
<dependency>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>jetty</artifactId>
    <version>6.1.26</version>
</dependency>

provider.xml 需要配置hessian協議,並給service設定

<?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://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
  http://www.springframework.org/schema/beans/spring-beans.xsd  
  http://code.alibabatech.com/schema/dubbo
  http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- 提供方應用資訊,用於計算依賴關係 -->
    <dubbo:application name="provider" />

    <!-- 使用zookeeper註冊中心暴露服務地址 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!-- 監控中心 -->
    <dubbo:monitor protocol="registry" />

    <!-- 暴露服務 -->
    <dubbo:protocol name="dubbo" port="20886" />
    <dubbo:protocol name="hessian" port="20887"/>

    <dubbo:service interface="com.dingcheng.user.facade.UserFacade" ref="userFacade" />

    <!-- 需要指定hessian協議,否則會在上面設定的協議中隨機呼叫,就會一會成功一會失敗 -->
    <dubbo:service protocol="hessian" interface="com.dingcheng.user.facade.UploadFacade" ref="uploadFacade" />
</beans>

其中 就是預設的 server="jetty", 如果設定server="servlet",則需要web容器支援,我們的provider是以jar方式執行的,所以不適用這種.

dubbo和hessiant特性

根據官方說明:Dubbo預設協議採用單一長連線和NIO非同步通訊,適合於小資料量大併發的服務呼叫,以及服務消費者機器數遠大於服務提供者機器數的情況

Hessian協議用於整合Hessian的服務,Hessian底層採用Http通訊,採用Servlet暴露服務。適用場景:傳入傳出引數資料包較大,提供者比消費者個數多,提供者壓力較大,可傳檔案。因此比較高效的做法是帶上傳下載檔案的服務使用hessian協議,去普通的服務使用dubbo協議。

Hessian以InputStream 做引數注意事項

Hessian 以InputStream 做引數的原理: 首先hessian要求inputstream 引數只能是引數列表中的最後一個,客戶端順序傳送各個引數,直到最後一個inputstream物件,讀取其內容,並寫入輸出流。 服務端獲取到請求輸入流後,按引數順序進行反序列化,直到遇到型別為InputStream的引數時,建立一個InputStream物件,實現InputStream的介面,其行為是從 輸入流讀取資料,該物件返回給開發者後就可以自由讀取流中剩餘的資料了(也就是傳參時從inputstream讀取出的所有資料)。

對於返回值是InputStream的情況,有兩種,一種是返回值就是一個InputStream物件,則服務端從中讀取資料並寫入輸出流,和輸入引數為InputStream的情況類似。 另一種是返回一個物件,物件中包含InputStream型別的欄位,這時一定要注意,InputStream欄位一定是所有非基本型別欄位裡的最後一個,原因同入參的情況一樣。 另外就是inputstream型別欄位不能超過1個。