1. 程式人生 > >Dubbo原始碼學習--Hession協議(四)

Dubbo原始碼學習--Hession協議(四)

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 介面
  • 引數及返回值不能自定義實現 ListMapNumberDateCalendar 等介面,只能用 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" />
1Hessian 是 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());
    }