为什么需要序列化和反序列化?


假设你是客户端,现在要调用远程的加法计算服务,你与服务端商定好了发送数据的格式:发送8个字节的请求,前4字节是第一个数,后4字节是第二个数,服务端读取数据的时候也按照商定的方式读取。其实,这就是一个序列化和反序列化的过程。序列化:2个数字变成8个字节数据,反序列化:8个字节数据变成2个数字。但是这么做有个问题,那就是太容易出错,每次你还得考虑按照什么形式排列字段,每个字段几个字节,还要考虑大端小端等。

为了解决这个重复性并且容易出错的过程,我们有一个小小的改进:把常用数据类型的序列化和反序列化代码封装成基础库:

int readInt(char *, int size) //读一个整数
int writeInt(int, char *, int size) //写一个整数
double readDouble(char *, int size) //读一个double型数
int writeDouble(double, char *, int size) //写一个double型数
float readFloat(char *, int size) //读一个浮点数
int writeFloat(float, char *, int size) //写一个浮点数
string readString(char *, int size) //读一个字符串
int writeString(string, char *, int size) //写一个字符串

现在,我们可以序列化任何基础类型数据。但是有个问题来了:怎么序列化结构体咧?仔细想一下,结构体也是由最基本的数据类型组成的啊,我们可能会有下面的方案:

class SimpleRequest { 
  int a;
  int b; int serialize(char *buf, int size) {
    writeInt(a, buf, size);
    writeInt(b, buf + , size - );
   return ;
} int deserialize(char *buf, int size) {
    a = readInt(buf, size);
    b = readInt(buf + , size - );
    return ;
  }
};

但有些结构体中套用结构体,这种情况怎么处理呢?很好办,因为只要是结构体我们就已经实现了serialize和deserialize接口,只要调用这两个函数就可以。所以,最终的方案就是:对于基础数据类型,通过readXX和writeXX序列化,结构体类型通过serialize/deserialize序列化。

由于基础数据类型数目有限可枚举,并且结构体定义也有一定的语法,我们完全可以设计一个语法解析器,读取IDL定义的文件,自动生成序列化和反序列化的代码。大致流程如下:使用BNF范式来编写规则,用来描述我们自己定义的IDL(接口描述语言);然后使用JAVACC或者YACC根据编写的BNF范式生成解析IDL语言的代码,利用生成的代码解析我们用IDL定义的结构体文件,根据语法树查找其中的基础数据类型、用户自定义结构体,并进行有针对性的进行解析。Thrift和grpc的IDL解析都是这么做的,有兴趣的同学可以自己玩一下Javacc和yacc。

SimpleRpc的序列化与反序列化设计方案


SimpleRpc没有自己的序列化和反序列化具体实现方案,它要求用户自己实现这部分代码。我们的例子中使用的protobuf,protobuf在SimpleRpc并不是必须的,你可以换成任何一种序列化方式。SimpleRpc的设计方案如下图所示:

Request和Response是请求和响应的基类,继承自Serializable接口,必须实现三个函数:

  1. serialize函数,把request/response序列化到参数指定的数组中。
  2. deserialize函数,把参数指定的数组中的二进制字节流反序列化成request/response。
  3. bytes函数,得到结构体序列化成字节流的大小。

AddRequest和AddResponse是用户端必须实现的代码,我的例子中在这两个类里面嵌套了protobuf定义的request和response,当框架根据多态调用序列化和反序列化函数时,相应的类通过调用其成员protobuf实例的序列化和反序列化代码。由于框架所看到的结构都是Request或者是Response,隐藏其中的protobuf对框架而言是不可见的,你可以更换成任意一种序列化和反序列化方式。

小伙伴们可能有疑问,为什么AddRequest和AddResponse不直接继承自Serialzable,而是继承自中间的那层Request和Response,是不是多余了?是因为,Request和Response除了实现序列化和反序列化之外,还有其它接口需要实现,这里面为了只突出序列化相关而忽略了其它接口。

与其它RPC的设计方案对比


最早接触到的序列化是在Java的远程调用RMI中,但是Java的序列化太笨拙,它不仅序列化数据成员,还序列化其对象间引用关系,这导致其序列化后的字节数非常多,不是一种高效率的手段。接下来遇到的就是ICE以及Thrift中序列化,但是其序列化模块是和整个框架绑定到一起,为了只用一个序列化功能,你必须安装整个框架,还是有些笨拙。直到遇到了protobuf,它真正的把序列化从RPC框架中抽离出来,成为了现在使用最多的序列化框架。

我们的RPC和其它的RPC的不同点就在于,序列化和框架是分离的,你可以自由更换序列化方式,只要你实现了Request和Response接口(你甚至都可以自己针对特定的请求响应硬编码字节流),给用户更多的选择性。

SimpleRpc-序列化与反序列化的设计与实现的更多相关文章

  1. 高性能的序列化与反序列化:kryo的简单使用

    前言:kryo是个高效的java序列化/反序列化库,目前Twitter.yahoo.Apache.strom等等在使用该技术,比如Apache的spark.hive等大数据领域用的较多. 为什么使用k ...

  2. DRF框架(三)——media资源路径设置、多表设计复习及补充、序列化组件(ModelSerializer)操作多表(序列化与反序列化)、多表序列化与反序列化整合(重点)

    media资源路径设置  (设置好后把图片放在这个文件夹中,通过链接能访问到图片) 1.先在根目录设置一个media文件夹 2.配置settings.py,加上下面的 MEDIA_URL = '/me ...

  3. C#对象序列化与反序列化zz

      C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍........................ ...

  4. C#对象序列化与反序列化

    C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍.......................... ...

  5. Asp.net中Json的序列化和反序列化(一)

    JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介绍 ...

  6. 序列化和反序列化的几种方式(JavaScriptSerializer 、XmlSerializer、DataContractSerializer)(一)

    JavaScriptSerializer 类 为启用 AJAX 的应用程序提供序列化和反序列化功能. 命名空间:   System.Web.Script.Serialization 程序集:  Sys ...

  7. ASP.NET中JSON的序列化和反序列化

    JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍 ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介 ...

  8. java中对象的序列化和反序列化

    [对象的序列化和反序列化 ] 1.定义:序列化--将对象写到一个输出流中.反序列化则是从一个输入流中读取一个对象.类中的成员必须是可序列化的,而且要实现Serializable接口,这样的类的对象才能 ...

  9. lintcode : 二叉树的序列化和反序列化

    题目 二叉树的序列化和反序列化 设计一个算法,并编写代码来序列化和反序列化二叉树.将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”. 如何反序列化或序列化二叉树是没有限制 ...

随机推荐

  1. 【Centos7】安装mysql5.7.16.tar.gz

    操作系统 centos7.1 云主机 1.下载好了压缩包到windows电脑上 2.使用Smartty的SCP传输到云主机的/home/xxx/下 3.解压 tar xvf  mysql-5.7.16 ...

  2. mysql 时间戳格式化函数FROM_UNIXTIME和UNIX_TIMESTAMP函数的使用说明

    我们一般使用字段类型int(11)时间戳来保存时间,这样方便查询时提高效率.但这样有个缺点,显示的时间戳,很难知道真实日期时间. MySQL提供了一个时间戳格式化函数from_unixtime来转换格 ...

  3. find the Nth highest salary(寻找第N高薪水)

    Suppose that you are given the following simple database table called Employee that has 2 columns na ...

  4. 四张图揭秘中国AI人才现状

    本文数据来源:领英<全球AI领域人才报告> 最近有非常多的同学看了之前我们的一些文章和直播之后,多对AI领域跃跃欲试,本文我们结合一份人才报告(我个人感觉这份报告还是比较靠谱的),为大家揭 ...

  5. 关于Java的发展前景

    各位看官觉得Java还能火几年?未来的发展方向是什么?

  6. LVS之DR模式实战及高可用性

    author:JevonWei 版权声明:原创作品 LVS-DR实现同网段调度web模式 拓扑环境 网络环境 RS1 RIP 192.168.198.138/24 VIP 192.168.198.10 ...

  7. css常用文本属性

    [CSS常用文本属性] 1. 字体.字号类: ① font-weight: 字体粗细. bold-加粗.normal-正常.lighter-细体 也可以使用100-900数值,400表示normal, ...

  8. Webservice优缺点总结

    优点: 1 .采用xml支持跨平台远程调用. 2.基于http的soap协议,可跨越防火墙. (因为SOAP一般使用HTTP协议,而服务器的这个协议一般都是开放的,而且是可以穿过防火墙的) 3.支持面 ...

  9. 第4阶段——制作根文件系统之分析init进程(2)

    本节目标: (1) 了解busybox(init进程和命令都放在busybox中) (2) 创建SI工程,分析busybox源码来知道init进程做了哪些事情 (3)  分析busybox中init进 ...

  10. css入门基础知识

    一.CSS常用选择器 /*CSS注释*/ /*CSS修改页面中的所有标签必须借助选择器选中. 选择器中可以写多对CSS属性:每个属性名与属性值之间用:分隔,多对属性之间,必须用;分隔 选择器{ 属性1 ...