`
云端月影
  • 浏览: 3065 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Hessian原理

阅读更多
Hessian 原理分析





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

网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 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 序列化的速度很快,而且序列化后的字节数也较其他技术少。
分享到:
评论

相关推荐

    Hessian应用

    这篇文档讲解的是Hessian的实现原理,简单易懂,是一个很好用的可以实现远程访问的技术!!!

    Hessian学习入门实例

    这是一个Hessian入门学习的实例,程序包是一个web工程,使用intellij idea + Maven开发,其中通过两个方式展示了使用Hessian实现RMI的原理,一个是访问jsp页面,一个是在代码中手工创建client。对于Hessian Servlet...

    Java远程通讯可选技术及原理

    在Java领域中有很多可实现远程通讯的技术,例如:RMI、MINA、ESB、 Burlap、Hessian、SOAP、EJB和JMS 等,这些名词之间到底是些什么关系呢,它们背后到底是基于什么原理实现的呢,了解这些是实现分布式服务框架的...

    论文研究-一种改进的3D血管增强算法.pdf

    基于Sato的血管增强原理,提出了一种改进算法。新算法将背景像素的Hessian矩阵特征值也考虑到滤波器的设计中,增强了滤波器滤除背景像素的功能。基于临床颈动脉的CTA数据和脑部血管MRA数据,做了实验分析。实验结果...

    梯度下降算法和牛顿算法原理以及使用python用梯度下降和最小二乘算法求回归系数

    梯度下降算法 以下内容参考 微信公众号 AI学习与实践平台 SIGAI ...至于是极大值还是极小值,要看二阶导数/Hessian矩阵,Hessian矩阵我们将在后面的文章中介绍,这是由函数的二阶偏导数构成的矩阵。这分为下面

    图像处理案例三之(2)SIFT特征点检测.docx

    而对于SURF来说,在每一组中选取相邻的三层Hessian行列式图像,对于中间层的每一个Hessian行列式值都可以做为待比较的点,在空间中选取该点周围的26个点进行比较大小,若该点大于其他26个点,则该点为特征点。...

    Java面试 Java分布式知识点 Java微服务知识点 面试知识点

    服务提供者能实现失效踢出是什么原理? 10 服务上线怎么不影响旧版本 10 如何解决服务调用链过长的问题? 10 dubbo核心配置 10 同一个服务多个注册的情况下可以直连某一个服务吗? 11 服务注册与发现的流程图 12 ...

    opencv3/C++ 实现SURF特征检测

    工作原理: 1、选择图像中POI(Points of Interest) Hessian Matrix; 2、在不同的尺度空间发现关键点,非最大信号压制; 3、发现特征点方法、旋转不变性要求; 4、生成特征向量; 类SURF中成员函数create()参数说明: ...

    分布式服务架构之java远程调用技术浅析

    在Java领域中有很多可实现远程通讯的技术,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,这些名词之间到底是些什么关系呢,它们背后到底是基于什么原理实现的呢,了解这些是实现分布式服务框架的基础...

    用于多目标目标的经典分子最优控制环境的拓扑

    本文考虑了激光驱动的一组非相互作用分子的最优控制,该非相互作用分子的动力学位于经典相空间中。 分子在控制下独立演化为不同的最终... 数值模拟表明了经典的景观原理,并随着控制领域的优化进一步表征了系统的行为。

    (二)OpenCV特征提取与检测_06_SURF特征检测

    工作原理 ①选择图像中POI(Points of Interest) Hessian Matrix ②在不同的尺度空间发现关键点,非最大信号压制 ③发现特征点方法、旋转不变性要求 ④生成特征向量 #include #include #include using namespace ...

    【毕业设计】针对Deepfake假脸视频面部细节特征的提取算法.zip

    一是原理简单易懂:SURF 有两大提高运算的法宝:integral images, box filters 在 Hessian 矩阵上的使用,降维特Descriptors的使用;ELA 利用 JPEG 全图相同压缩率的特点做差对比。二是有现成的库函数可以实现这两个...

    Wolf 方法的二次规划:函数 wolf 使用 Wolf 或限制入口单纯形法求解(凸)QPP-matlab开发

    为了算法的收敛性,目标函数的 Hessian 要么是正定的,要么是线性项为零的正半定 Hessian。 对于 Wolf 方法和 QPP 的理论,您可以参阅“应用应用的数值优化,Chandra S.、Jayadeva、Mehra A.、Alpha Science ...

    伪距、伪距率、航向角观测模型的AHRS/GPS QEKF算法 (2008年)

    根据 Tay-lor展开原理,通过对 Hessian矩阵的求解,补偿系统观测方程线性化的二阶截断误差。仿真表明,QEKF所建模 型符合实际导航系统要求,可使姿态角、位置误差均方差分别控制在90 s和3 m以内,优于相同条件下标准 EKF ...

    UKF算法在纯方位目标运动分析中的应用 (2008年)

    由于UKF在处理非线性问题时表现良好,以及不需要计算Jacobian矩阵或Hessian矩阵,实现起来比较方便。根据无味变换的基本原理给出了滤波过程的具体计算步骤并进行了仿真计算。理论分析和仿真结果表明,UKF的性能相当...

    Java实现简单的RPC框架

    RPC,全称为RemoteProcedureCall,即远程过程调用,它是一个计算机通信协议。它允许像调用本地服务一样调用远程服务。它可以有不同的实现方式。如RMI(远程方法调用)、Hessian、...上面介绍了RPC的核心原理:RPC

    Spring 2.0 开发参考手册

    3.2. 容器和bean的基本原理 3.2.1. 容器 3.2.2. 实例化容器 3.2.3. 多种bean 3.2.4. 使用容器 3.3. 依赖 3.3.1. 注入依赖 3.3.2. 构造器参数的解析 3.3.3. bean属性及构造器参数详解 3.3.4. 使用depends-on...

    spring chm文档

    3.2. 容器和bean的基本原理 3.2.1. 容器 3.2.2. 实例化容器 3.2.3. 多种bean 3.2.4. 使用容器 3.3. 依赖 3.3.1. 注入依赖 3.3.2. 构造器参数的解析 3.3.3. bean属性及构造器参数详解 3.3.4. 使用depends-on...

Global site tag (gtag.js) - Google Analytics