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個。