`

转:Hessian 原理分析

    博客分类:
  • Java
阅读更多
原文:http://blog.csdn.net/zhtang0526/archive/2009/11/09/4788879.aspx

一.      远程通讯协议的基本原理

网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 http 、 tcp 、 udp 等等, http 、 tcp 、 udp 都是在基于 Socket 概念上为某类应用场景而扩展出的传输协议,网络 IO ,主要有 bio 、 nio 、 aio 三种方式,所有的分布式应用通讯都基于这个原理而实现,只是为了应用的易用,各种语言通常都会提供一些更为贴近应用易用的应用层协议。

二.      应用级协议 Binary-RPC

Binary-RPC 是一种和 RMI 类似的远程调用的协议,它和 RMI 的不同之处在于它以标准的二进制格式来定义请求的信息 ( 请求的对象、方法、参数等 ) ,这样的好处是什么呢,就是在跨语言通讯的时候也可以使用。

来看下 Binary -RPC 协议的一次远程通信过程:

1 、客户端发起请求,按照 Binary -RPC 协议将请求信息进行填充;

2 、填充完毕后将二进制格式文件转化为流,通过传输协议进行传输;

3 、接收到在接收到流后转换为二进制格式文件,按照 Binary -RPC 协议获取请求的信息并进行处理;

4 、处理完毕后将结果按照 Binary -RPC 协议写入二进制格式文件中并返回。

         问题总结:

1 、传输的标准格式是?

    标准格式的二进制文件。

2 、怎么样将请求转化为传输的流?

    将二进制格式文件转化为流。

3 、怎么接收和处理流?

    通过监听的端口获取到请求的流,转化为二进制文件,根据协议获取请求的信息,进行处理并将结果写入 XML 中返回。

4 、传输协议是?

Http 。

三.      Hessian ——一种实现远程通讯的 library

Hessian 是由 caucho 提供的一个基于 binary-RPC 实现的远程通讯 library 。

1 、是基于什么协议实现的?

基于 Binary-RPC 协议实现。

2 、怎么发起请求?

需通过 Hessian 本身提供的 API 来发起请求。

3 、怎么将请求转化为符合协议的格式的?

Hessian 通过其自定义的串行化机制将请求信息进行序列化,产生二进制流。

4 、使用什么传输协议传输?

Hessian 基于 Http 协议进行传输。

5 、响应端基于什么机制来接收请求?

响应端根据 Hessian 提供的 API 来接收请求。

6 、怎么将流还原为传输格式的?

Hessian 根据其私有的串行化机制来将请求信息进行反序列化,传递给使用者时已是相应的请求信息对象了。

7 、处理完毕后怎么回应?

             处理完毕后直接返回, hessian 将结果对象进行序列化,传输至调用端。

四.      Hessian 源码分析

以 hessian 和 spring dm server 整合环境为例。

1.     客户端发起请求

Hessian 的这个远程过程调用,完全使用动态代理来实现的。有客户端可以看出。

除去 spring 对其的封装,客户端主要是通过 HessianProxyFactory 的 create 方法就是创建接口的代理类,该类实现了接口, JDK 的 proxy 类会自动用 InvocationHandler 的实现类(该类在 Hessian 中表现为 HessianProxy )的 invoke 方法体来填充所生成代理类的方法体。

客户端系统启动时:

         根据 serviceUrl 和 serviceInterface 创建代理。

         HessianProxyFactoryBean 类

       

HessianClientInterceptor 类

                  createHessianProxy(HessianProxyFactory proxyFactory)



HessianProxyFactory 类

                  public Object create(Class api, String urlName)



客户端调用 hessian 服务时:

                   HessianProxy 类的 invoke(Object proxy, Method method, Object []args) 方法

                            String methodName = method.getName();// 取得方法名

                            Object value = args[0]; // 取得传入参数

                            conn = sendRequest(mangleName, args) ;      // 通过该方法和服务器端取得连接



                            httpConn = (HttpURLConnection) conn;

                            code = httpConn.getResponseCode();    // 发出请求



// 等待服务器端返回相应…………



                            is = conn.getInputStream();

                            Object value = in.readObject(method.getReturnType()); // 取得返回值



HessianProxy 类的 URLConnection sendRequest(String methodName, Object []args) 方法:

                      URLConnection  conn = _factory.openConnection(_url);      // 创建 URLConnection

                            OutputStream os = conn.getOutputStream();



                            AbstractHessianOutput out = _factory.getHessianOutput(os); // 封装为 hessian 自己的输入输出 API

                            out.call(methodName, args);

                            return conn;

       



2.     服务器端接收请求并处理请求

服务器端截获相应请求交给:

org.springframework.remoting.caucho.HessianServiceExporter

具体处理步骤如下:

a)       HessianServiceExporter 类

(HessianExporter) invoke(request.getInputStream(), response.getOutputStream());



b)       HessianExporter 类

(Hessian2SkeletonInvoker) this.skeletonInvoker.invoke(inputStream, outputStream);

c)       Hessian2SkeletonInvoker 类

将输入输出封转化为转化为 Hessian 特有的 Hessian2Input 和 Hessian2Output

      Hessian2Input in = new Hessian2Input(isToUse);

      in.setSerializerFactory(this.serializerFactory);



      AbstractHessianOutput out = null;

      int major = in.read();

      int minor = in.read();

      out = new Hessian2Output(osToUse);

      out = new HessianOutput(osToUse);

      out.setSerializerFactory(this.serializerFactory);

      (HessianSkeleton) this.skeleton.invoke(in, out);



d)       HessianSkeleton 类

           读取方法名

         String methodName = in.readMethod();

    Method method = getMethod(methodName);

           读取方法参数

         Class []args = method.getParameterTypes();

    Object []values = new Object[args.length];



           执行相应方法并取得结果

         result = method.invoke(service, values);



           结果写入到输出流

         out.writeObject(result);

       

总结: 由上面源码分析可知,客户端发起请求和服务器端接收处理请求都是通过 hessian 自己的 API 。输入输出流都要封装为 hessian 自己的 Hessian2Input 和 Hessian2Output ,接下来一节我们将去了解 hessian 自己封装的输入输出到底做了些什么!

五.      Hessian 的序列化和反序列化实现

hessian 源码中 com.caucho.hessian.io 这个包是 hessian 实现序列化与反序列化的核心包。其中 AbstractSerializerFactory , AbstractHessianOutput , AbstractSerializer , AbstractHessianInput , AbstractDeserializer 是 hessian 实现序列化和反序列化的核心结构代码。



1.         AbstractSerializerFactory ,它有 2 个抽象方法:

根据类来决定用哪种序列化工具类

abstract public Serializer getSerializer(Class cl)  throws HessianProtocolException;

根据类来决定用哪种反序列化工具类

abstract public Deserializer getDeserializer(Class cl)  throws HessianProtocolException;

2.         SerializerFactory 继承 AbstractSerializerFactory 。

在 SerializerFactory 有很多静态 map 用来存放类与序列化和反序列化工具类的映射,这样如果已经用过的序列化工具就可以直接拿出来用,不必再重新实例化工具类。

在 SerializerFactory 中,实现了抽象类的 getSerializer 方法,根据不同的需要被序列化的类来获得不同的序列化工具,一共有 17 种序列化工具, hessian 为不同的类型的 java 对象实现了不同的序列化工具,默认的序列化工具是 JavaSerializer 。

在 SerializerFactory 中,也实现了抽象类的 getDeserializer 方法,根据不同的需要被反序列化的类来获得不同的反序列化工具,默认的反序列化工具类是 JavaDeserializer 。

3.         HessianOutput 继承 AbstractHessianOutput 成为序列化输出流的一种实现。

它会实现很多方法,用来做流输出。

需要注意的是方法,它会先调用 serializerFactory 根据类来获得 serializer 序列化工具类

public void writeObject(Object object)

throws IOException

{

if (object == null) {

writeNull();

return;

}



Serializer serializer;



serializer = _serializerFactory.getSerializer(object.getClass()); 



serializer.writeObject(object, this);

}

4.         现在我们来看看 AbstractSerializer 。

其 writeObject 是必须在子类实现的方法, AbstractSerializer 有 17 种子类实现, hessian 根据不同的 java 对象类型来实现了不同的序列化工具类,其中默认的是 JavaSerializer 。

而 JavaSerializer 的 writeObject 方法的实现,遍历 java 对象的数据成员,根据数据成员的类型来获得各自的 FieldSerializer ,一共有 6 中默认的 FieldSerializer 。

拿默认的 FieldSerializer 举例,还是调用 AbstractHessianOutput 的子类来 writeObject ,这个时候,肯定能找到相应的 Serializer 来做序列化



同理可以反推出 hessian 的反序列化机制。 SerializerFactory 可以根据需要被反序列化的类来获得反序列化工具类来做反序列化操作。



总结:得益于 hessian 序列号和反序列化的实现机制, hessian 序列化的速度很快,而且序列化后的字节数也较其他技术少。











参考文献:

1.       《 Java 远程通讯可选技术及原理》 http://java.chinaitlab.com/base/740383.html

2.       《 Hessian-3.2.0 源码》

3.       《 hessian 序列化实现初探》 http://www.javaeye.com/topic/245238

4.       《 Hessian 2.0 序列化协议规范》

http://blog.csdn.net/xpspace/archive/2007/10/05/1811603.aspx
分享到:
评论

相关推荐

    hessian-4.0.63-API文档-中文版.zip

    Maven坐标:com.caucho:hessian:4.0.63; 标签:hessian、caucho、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构...

    hessian-3.3.6-API文档-中文版.zip

    Maven坐标:com.alipay.sofa:hessian:3.3.6; 标签:sofa、hessian、alipay、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的...

    hessian-4.0.63-API文档-中英对照版.zip

    Maven坐标:com.caucho:hessian:4.0.63; 标签:hessian、caucho、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和...

    hessian-3.3.6-API文档-中英对照版.zip

    赠送jar包:hessian-3.3.6.jar 赠送原API文档:hessian-3.3.6-javadoc.jar 赠送源代码:hessian-3.3.6-sources.jar 包含翻译后的API文档:hessian-3.3.6-javadoc-API文档-中文(简体)-英语-对照版.zip 对应Maven...

    hessian-3.0.20-src.jar

    hessian是一个轻量级的Java Remoting方案

    轻量级的remoting on http工具(最新):hessian-4.0.60

    Hessian一般是通过Web应用来提供服务,因此非常类似于平时我们用的 WebService。 只是它不使用SOAP协议,但相比webservice而言更简单、快捷。

    hessianAnalysisDemo:Hessian 分析如何揭示规模不佳的估计问题的演示-matlab开发

    这是 Hessian 分析如何揭示参数估计问题规模不佳的演示。 研究的模型是非线性的,局部线性化是通过数值方式完成的。 原则上,此代码可适用于对任何非线性模型进行类似分析。 提交使用了非常有用的 DERVIEST 套件的...

    qhessian:hessian 协议的 Qt && C++ 实现

    hessian 协议的 Qt && C++ 实现 QHessian 基于 Qt 框架。 这意味着您只需要 qt 框架即可使用 hessian 的所有功能。 无需生成代码即可使用 qhessian。 C++ 实现的比较: 项目 代码生成 图书馆 是的 卷曲 不 SSLPP ...

    hessian-lite-3.2.1-fixed-2.jar

    com.alibaba:hessian-lite:jar:3.2.1-fixed-2 hessian-lite hessian-lite-3.2.1-fixed-2.jar

    Hessian的jar包.zip

    收集的jar包,实际使用无问题,欢迎下载,如不能使用,请及时联系发布者 简介:hessian的4.0.33.jar

    hhydra:hessian协议实现的Hydra关键部分服务

    hessian协议实现的Hydra关键部分服务 用法 运行服务器 服务器配置文件 hhydra.conf 的内容: port=50201 storeConfigFile=hhydra-storage.xml host=sicx1.hip.helsinki.fi sslCertFile=hostcert.pem sslKey=host...

    hessian与spring整合的jar包

    hessian与spring整合的jar包

    SpringMVC+ibatis+hessian基础框架

    压缩包里有两个 springMVC+Ibatis 的项目:HessianServer(服务器端),HessianClient(客户端),解压导入到MyEclipse 更改配置文件中的数据源,建表(和实体类对应的表),执行客户端中的BasicClient.java文件即可...

    hessian-4.0.3

    来自于caucho的通过HTTP协议实现远程方法调用的jar包:hessian-4.0.3。

    Hessian源码分析和Hack.doc

    项目选定Hessian作为web service的实现方式,确实很轻量级,速度就跟直接用socket差不多,全是二进制传送节约了不少开销。但是在使用过程中有业务需要是必须获得远程端的ip地址,主机名等信息的。翻便Hessian的文档...

    hessian案例,hessian案例

    该案例有hessian java python,该案例有hessian java python,该案例有hessian java python

    Hessian多个版本打包下载

    Hessian多个版本下载,包括Hessian3.1.6,Hessian3.2.1,Hessian4.0.7

    Hessian样例源代码

    1、开发环境:eclipse3.1 + jdk1.5; 2、样例说明: 1)spring + hessian; 2)hessian。 3、样例内容: 1)HashMap传递; 2)简单对象传递; 3)异常处理

    hessian 源代码与jar包

    Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据

    Hessian实例下载

    Hessian实例 网站地址:http://hessian.caucho.com/#Java可以下载Hessian需要的jar包 2010.11.11上传

Global site tag (gtag.js) - Google Analytics