1.1 序列化技术
- 序列化的作用
在网络传输中,数据必须采用二进制形式, 所以在 RPC 调用过程中, 需要采用序列化技术,对入参对象和返回值对象进行序列化与反序列化。 - 如何进行序列化
自定义的二进制协议来实现序列化:
一个对象是如何进行序列化? 下面以 User 对象例举讲解:
User 对象:
package com.itcast;
public class User {
/**
* 用户编号
*/
private String userNo = "0001";
/**
* 用户名称
*/
private String name = "zhangsan";
}
包体的数据组成:
业务指令为 0x00000001 占 1 个字节,类的包名 com.itcast 占 10 个字节, 类名 User 占 4 个字节;
属性 UserNo 名称占 6 个字节,属性类型 string 占 2 个字节表示,属性值为 0001 占 4 个字节;
属性 name 名称占 4 个字节,属性类型 string 占 2 个字节表示,属性值为 zhangsan 占 8 个字节;
包体共计占有 1+10+4+6+2+4+4+2+8 = 41 字节。
包头的数据组成:
版本号 v1.0 占 4 个字节,消息包体实际长度为 41 占 4 个字节表示,序列号 0001 占 4 个字节,校验码 32 位表示占 4 个字节。
包头共计占有 4+4+4+4 = 16 字节。
包尾的数据组成:
通过回车符标记结束 \r\n,占用 1 个字节。
整个包的序列化二进制字节流共 41+16+1 = 58 字节。这里讲解的是整个序列化的处理思路, 在实际的序列化处理中还要考虑更多细节,比如说方法和属性的区分,方法权限的标记,嵌套类型的处理等等。
- 序列化的处理要素
- 解析效率:序列化协议应该首要考虑的因素,像 xml/json 解析起来比较耗时,需要解析 doom 树,二进制自定义协议解析起来效率要快很多。
- 压缩率:同样一个对象,xml/json 传输起来有大量的标签冗余信息,信息有效性低,二进制自定义协议占用的空间相对来说会小很多。
- 扩展性与兼容性:是否能够利于信息的扩展,并且增加字段后旧版客户端是否需要强制升级,这都是需要考虑的问题,在自定义二进制协议时候,要做好充分考虑设计。
- 可读性与可调试性:xml/json 的可读性会比二进制协议好很多,并且通过网络抓包可以直接读取,二进制则需要反序列化才能查看其内容。
- 跨语言:有些序列化协议是与开发语言紧密相关的,例如 dubbo 的 Hessian 序列化协议就只能支持 Java 的 RPC 调用。
- 通用性:xml/json 非常通用,都有很好的第三方解析库,各个语言解析起来都十分方