Dubbo原始碼學習--Hession協議(四)
阿新 • • 發佈:2018-12-26
Hessian 1 協議用於整合 Hessian 的服務,Hessian 底層採用 Http 通訊,採用 Servlet 暴露服務,Dubbo 預設內嵌 Jetty 作為伺服器實現。
Dubbo 的 Hessian 協議可以和原生 Hessian 服務互操作,即:
- 提供者用 Dubbo 的 Hessian 協議暴露服務,消費者直接用標準 Hessian 介面呼叫
- 或者提供方用標準 Hessian 暴露服務,消費方用 Dubbo 的 Hessian 協議呼叫。
特性
- 連線個數:多連線
- 連線方式:短連線
- 傳輸協議:HTTP
- 傳輸方式:同步傳輸
- 序列化:Hessian二進位制序列化
- 適用範圍:傳入傳出引數資料包較大,提供者比消費者個數多,提供者壓力較大,可傳檔案。
- 適用場景:頁面傳輸,檔案傳輸,或與原生hessian服務互操作
依賴
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.7</version>
</dependency>
約束
- 引數及返回值需實現
Serializable
介面 - 引數及返回值不能自定義實現
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. Hessian 是 Caucho 開源的一個 RPC 框架,其通訊效率高於 WebService 和 Java 自帶的序列化。
HessionProtocol和HttpProtocol基本類似,都是通過servlet容器對外提供服務,最終都是基於http進行服務呼叫,不過其整個實現原理是基於Hession框架來的,可以閱讀一下博主之前有關hession學習相關的部落格。
HessionProtocol同樣也是提供了兩個介面doExport和doRefer
(1)doExport中簡單來說是暴露服務,但是HessionProtocol其真正是通過容器(內建容器tomcat和jetty或者外部容器)來暴露服務,其只需要將其配置初始化到容器即可。
protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException {
String addr = getAddr(url);
HttpServer server = serverMap.get(addr);
if (server == null) {
server = httpBinder.bind(url, new HessianHandler());
serverMap.put(addr, server);
}
final String path = url.getAbsolutePath();
//根據介面及url對外暴露服務
HessianSkeleton skeleton = new HessianSkeleton(impl, type);
skeletonMap.put(path, skeleton);
//建立執行緒用於銷燬服務使用
return new Runnable() {
public void run() {
skeletonMap.remove(path);
}
};
}
(2)doRefer中簡單來說就是組建遠端呼叫的IP、埠、上下文和路徑資訊建立代理類,通過http協議來完成遠端呼叫,在遠端呼叫時消費者會根據url將要呼叫的介面、方法及引數資訊傳送給服務提供者,服務提供者根據介面和方法進行反射獲取實現類,根據引數執行獲取結果,在將結果返回給服務消費者。 @SuppressWarnings("unchecked")
protected <T> T doRefer(Class<T> serviceType, URL url) throws RpcException {
//建立hession代理工廠
HessianProxyFactory hessianProxyFactory = new HessianProxyFactory();
boolean isHessian2Request = url.getParameter(Constants.HESSIAN2_REQUEST_KEY, Constants.DEFAULT_HESSIAN2_REQUEST);
hessianProxyFactory.setHessian2Request(isHessian2Request);
boolean isOverloadEnabled = url.getParameter(Constants.HESSIAN_OVERLOAD_METHOD_KEY, Constants.DEFAULT_HESSIAN_OVERLOAD_METHOD);
hessianProxyFactory.setOverloadEnabled(isOverloadEnabled);
String client = url.getParameter(Constants.CLIENT_KEY, Constants.DEFAULT_HTTP_CLIENT);
if ("httpclient".equals(client)) {
hessianProxyFactory.setConnectionFactory(new HttpClientConnectionFactory());
} else if (client != null && client.length() > 0 && !Constants.DEFAULT_HTTP_CLIENT.equals(client)) {
throw new IllegalStateException("Unsupported http protocol client=\"" + client + "\"!");
}
int timeout = url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
hessianProxyFactory.setConnectTimeout(timeout);
hessianProxyFactory.setReadTimeout(timeout);
//代理工廠根據介面、http相關資訊建立代理類
return (T) hessianProxyFactory.create(serviceType, url.setProtocol("http").toJavaURL(), Thread.currentThread().getContextClassLoader());
}