当前位置: 首页 > article >正文

RPC远程调用的序列化框架

序列化框架对比:

在这里插入图片描述

一、Java Serialiazer

字段serialVersionUID的作用是为了在序列化时保持版本的兼容性,即版本升级时反序列化仍保持对象的唯一性。

//序列化
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutoutStream out = new ObjectOutputStream(bout);
out.writeObject(obj);
byte[] bytes = bout.toByteArray();

//反序列化
ObjectInputStream bin = new ObjectInputStream(new ByteArrayInputStream(bytes));
bin.readObject();

二、Hessian

底层基于list和HashMap实现
其在序列化的类有父类的时候,如果有字段相同,父类的值会覆盖子类的值,因此使用时一定要注意子类和父类不能有同名字段

Hessian的实现有v1和v2两个版本,并不兼容。推荐使用Hessian2相关的类

//序列化
ByteArrayOutputStream os = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(os);
out.startMessage();
TestUser user = new TestUser();
out.writeObject(user);
out.completeMessage()
out.flush();
byte[] bytes = os.toByteArray();
out.close();
os.close();

//反序列化
ByteArrayInputStream ins = new ByteArrayInputStream(bytes);
Hessian2Input input = new Hessian2Input(ins);
input.startMessage();
TestUser newUser = (TestUser)input.readObject();
input.completeMessage();
input.close();
ins.close();

三、MsgPack

需要在序列化的类上加@Message注解
为了保证序列化向后兼容,新增加的属性需要加在类的最后面,且要加@Optional注解

MsgPack提供了动态类型的功能,通过接口Value来实现动态类型
首先将数组序列化为Value类型的对象,然后用converter转化为本身的类型

//TestUser.java
@Message
public class TestUser{
	private String name;
	private String mobile;
	//...
}

TestUser user = new TestUser();
MessagePack messagePack = new MessagePack();

//序列化
byte[] bs = messagePack.write(user);

//反序列化
user = messagePack.read(bs,TestUser.class);

四、Kryo

Kryo kryo = new Kryo();

//序列化
ByteArrayOutputStream os = new ByteArrayOutputStream();
Output output = new Output(os);
TestUser user = new TestUser();
kryo.writeObject(output,user);
output.close();
byte[] bytes = os.toByteArray();

//反序列化
Input input = new Input(new ByteArrayInputStream(bytes));
TestUser newUser = kryo.readObject(input,TestUser.class);
input.close();

五、Thrift

需要先定义IDL,再使用Thrift

//定义IDL
//TestUser.thrift
namespace java.me.rowkey.pje.datatrans.rpc.thrift

struct TestUser{
	1: required string name
	2: required string mobile
}

thrift --gen java TestUser.trhrift

使用生成的TestUser类做序列化和反序列化

TestUser user = new TestUser();//由Thrift代码生成引擎生成

//序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
user.write(new TBinaryProtocol(new TIOStreamTransport(bos)));
byte[] result = bos.toByteArray();
bos.close();

//反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(result);
TestUser user = new TestUser();
user.read(new TBinaryProtocol(new TIOStreamTransport(bis)));
bis.close();

由于Thrift序列化时,丢弃了部分信息,故使用ID+Type来做标识
因此对新增的字段属性采用ID递增的方式标识并以Optional修饰来添加,这样才能做到向后兼容

六、Protobuf

Google开源的序列化框架

首先需要编写.proto文件,并使用Protobuf代码生成引擎生成Java代码

//TestUser.proto
syntax = "proto3";
option java_package = "me.rowkey.pje.datatras.rpc.proto";
option java_outer_classname = "TestUserProto";
message TestUser{
	string name = 1;
	string mobile = 2;
}

protoc --java_out = ./TestUser.proto

即生成TestUserProto.java,使用此类即可完成序列化和反序列化

//序列化
TestUserProto.TestUser testUser = TestUserProto.TestUser.newBuilder()
												.setMobile("xxx")
												.setName("xxx")
												.build();
byte[] bytes = testUser.toByteArray();

//反序列化
testUser = TestUserProto.TestUser.parseFrom(bytes);

使用提示:

面对RPC框架,选择的时候需要一下方面进行选择

  • 是否允许代码侵入,即需要依赖响应的代码生成器生成代码,入Thrift
  • 是否需要长连接获取高性能,如果性能需求高,则选择基于TCP的Thrift/Dubbo
  • 是否需要跨网段、跨防火墙,需要基于HTTP协议的Hessian和Thrift的HTTP Transport

http://www.kler.cn/news/305600.html

相关文章:

  • 【python】OpenCV—Age and Gender Classification
  • Threejs合并模型动画(上)
  • quartz 搭配SQL Server时出现deadlock的解决方案
  • ClickHouse总结
  • 如何使用 Vue 3 的 Composition API
  • C++ | Leetcode C++题解之第406题根据身高重建队列
  • 阿里部分集团内部中间件简介
  • 【Elasticsearch系列四】ELK Stack
  • DroidBot-GPT: GPT-powered UI Automation for Android论文学习
  • C++学习笔记----7、使用类与对象获得高性能(一)---- 书写类(2)
  • 【编程基础知识】Java语言中字面字符和转义字符的区别
  • 自建,前端sdk库(react-utils-dev-sdk)
  • Pytorch2.4.0自动安装cudnn9.1??? pip安装cudnn方法
  • 使用SQLAlchemy进行数据库操作:编写一个高效的Python函数
  • SpringBoot和SpringMVC是什么关系?SpringBoot替代SpringMVC了吗?
  • 继图书管理项目遗留的问题修改
  • Google宣布所有英语语种的Gemini Live用户现可免费使用
  • 对游戏语音软件Oopz遭遇DDoS攻击后的一些建议
  • 深入了解 Python 的 argparse 模块:命令行参数处理的艺术
  • 828华为云征文 | 华为云X实例服务器上部署知识图谱项目的详细指南
  • 企微机器人:企业数字化转型的得力助手
  • dubbo一
  • 重拾java-------day2(下载,特点,运行过程,环境变量)
  • React 中的事件绑定与参数传递
  • 尚品汇-订单拆单、支付宝关闭交易、关闭过期订单整合(五十)
  • 《网络协议 - HTTP传输协议及状态码解析》
  • 伙房食堂电气安全新挑战:油烟潮湿环境下,如何筑起电气火灾“防火墙”?
  • Linux——分离部署,分化压力
  • Next.js 14 如何在服务端页面中使用客户端渲染组件
  • Python数据分析-Pandas快速入门