`

转: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

    **三、Hessian工作原理** 1. **序列化**:在服务端,Hessian将Java对象转换为二进制流,这个过程称为序列化。 2. **网络传输**:序列化后的二进制流被发送到客户端,通过HTTP协议进行传输。 3. **反序列化**:在...

    Hessian源代码

    这个压缩包文件“hession_1”包含了Hessian的源代码以及相关的示例,这将有助于我们深入理解其内部工作原理。 Hessian协议的主要特点包括: 1. **二进制格式**:与基于文本的HTTP协议不同,Hessian使用二进制格式...

    hessian

    在【标签】中,"源码"可能指的是查看或分析Hessian协议的底层实现,这对于理解其工作原理和优化性能非常有帮助。"工具"可能指的是使用Hessian相关的开发工具或框架,例如HessianProxyFactory、HessianServlet等。 ...

    Hessian 入门介绍

    通过运行和分析`HessianDemo`,你可以更深入地理解Hessian的工作流程,包括如何创建服务端的Hessian服务,如何在客户端使用Hessian Proxy进行调用,以及如何处理返回结果。 总之,Hessian作为一种高效的RPC协议,...

    自己写了个Hessian

    通过分析这些测试代码,我们可以更深入地了解Hessian的工作原理,以及如何在不同的场景下使用它。 总之,"自己写了个Hessian" 是一个关于实现Hessian协议的个人项目,涉及到对象序列化、HTTP通信、RPC服务等多个IT...

    Hessian 学习 例子 实例

    至于"工具",有一些工具可以帮助开发者测试和调试Hessian服务,例如,Hessian Proxy工具允许你通过HTTP代理的方式交互Hessian服务,以便观察和分析传输的二进制数据。 总的来说,Hessian是一个值得学习的技术,尤其...

    Hessian应用

    ### Hessian应用 #### Hessian概述 Hessian是一种轻量级的远程过程调用(Remote Procedure Call,RPC)协议,由...通过对其实现原理的理解,我们可以更好地利用Hessian来解决实际问题,提高系统的性能和灵活性。

    Hessian入门案例源代码

    在“Hessian入门案例源代码”中,我们可以通过分析HessianDemo这个项目来学习如何使用Hessian。源代码通常包括服务器端和客户端两部分,它们展示了如何定义服务接口、实现服务、发布服务以及如何调用这些服务。 1. ...

    二进制Web服务Hessian刘骥讲座--(附源码)

    5. **源码附赠**:刘骥的讲座可能包含了Hessian服务的示例源码,这对于学习和理解Hessian的工作原理及其实际应用非常有帮助。通过分析和实践这些源码,开发者可以深入理解如何在自己的项目中集成和使用Hessian。 6....

    Hessian 发布WebServices

    标题 "Hessian 发布WebServices" 指的是使用Hessian协议来构建和发布Web服务。Hessian是一种二进制的远程过程调用(RPC)协议,它旨在提供...通过分析和理解源代码,可以进一步提升对Hessian协议和Web服务开发的理解。

    spring整合hessian进行远程通讯

    标题中的“spring整合hessian进行远程通讯”是指在Spring框架中使用Hessian库来实现远程过程调用(RPC)。...在实际开发中,我们需要结合源码学习,了解其实现原理,并注意安全性和性能优化,确保系统的稳定运行。

    Spring中集成Hessian的问题

    Hessian的源码分析可以帮助我们更深入地理解其工作原理。Hessian服务端的序列化和反序列化过程、HTTP请求处理以及异常处理等都是关键部分。而Spring框架如何与Hessian进行集成,包括服务注册、请求处理和代理创建等...

    Hessian协议格式

    Hessian 协议格式 Hessian 协议是一种轻量级的 remoting on http 工具,使用简单的方法...通过对 Hessian 协议报文格式的分析,我们可以更好地理解 Hessian 协议的工作原理,并更好地应用 Hessian 协议在实际项目中。

    hessian-4.0.7.jar + src

    本次我们将深入探讨Hessian 4.0.7版本,包括其jar包的使用以及源码分析,帮助开发者更好地理解和应用这个强大的工具。 一、Hessian 4.0.7.jar——核心库 `hessian-4.0.7.jar`是Hessian的核心库文件,它包含了...

    hessian_test02.rar

    一、Hessian原理与特性 1. Hessian采用了二进制格式,相比于传统的XML或JSON序列化方式,数据传输量更小,从而提高了网络传输效率。 2. 支持跨语言调用,虽然主要应用于Java,但也有其他语言的实现,如C++、Python等...

    hessian3.1和spring2.5的结合

    例如,了解`HessianProxyFactoryBean`的工作原理,以及Hessian协议如何序列化和反序列化对象。 10. **工具支持**: 使用诸如IDEA或Eclipse这样的集成开发环境,可以方便地管理和调试Hessian服务。同时,还可以借助...

    flex中hessian实例

    1. **Hessian协议**:理解Hessian的基本原理,包括它的二进制编码规则、如何序列化和反序列化对象,以及如何处理不同类型的数据,如基本类型、复杂对象和数组。 2. **Flex中的Hessian服务**:在Flex项目中如何配置...

    基于python的Hessian Frangi滤波算法设计与实现

    2. 特征值分析:计算Hessian矩阵的特征值λ1, λ2, λ3。特征值的大小和符号关系到图像特征的形状和方向。 3. 弹性网络模型:使用Frangi提出的弹性网络模型,结合特征值来评估该像素点是否属于血管结构。这通常涉及...

    hessian-demo示例

    首先,让我们深入了解Hessian的工作原理。Hessian协议基于HTTP,但采用了二进制编码,从而减少了网络传输的数据量,提高了通信效率。它支持基本类型、对象、数组以及XML和JSON等数据格式的序列化和反序列化。在Java...

Global site tag (gtag.js) - Google Analytics