Thrift = 序列化/反序列化 + RPC协议(client/server也生成了)
特点:
1.Thrift支持多种语言(C++,C#,Cocoa,Erlag,Haskell,java,Ocami,Perl,PHP,Python,Ruby,和SmallTalk)
2.Thrift适用了组建大型数据交换及存储工具,对于大型系统中的内部数据传输,相对于Json和xml在性能上和传输大小上都有明显的优势。
3.Thrift支持三种比较典型的编码方式。(通用二进制编码,压缩二进制编码,优化的可选字段压缩编解码)
Protocol Buffer = 单纯的序列化/反序列化,是google开源的项目
https://developers.google.cn/protocol-buffers
https://github.com/protocolbuffers/protobuf
特点:
1.结构化数据存储格式(xml,json等)
2.高性能编解码技术
3.语言和平台无关,扩展性好
4.支持java,C++,Python三种语言。
gRPC = 以Protocol Buffer为基础的序列化/反序列化 + RPC协议(client/server也生成了)
Protostuff = 基于谷歌Protocal Buffer的序列化库
https://github.com/protostuff/protostuff
特点:
相对我们常用的json来说,Protocol Buffer门槛更高,因为需要编写.proto文件,再把它编译成目标语言,这样使用起来就很麻烦
但是现在有了protostuff之后,就不需要依赖.proto文件了,他可以直接对POJO进行序列化和反序列化,使用起来非常简单。
hessian =
特点:
1.默认支持跨语言
2.较慢
JSON序列化 =
1、Jackson
相比json-lib框架,Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。
而且Jackson社区相对比较活跃,更新速度也比较快。
Jackson对于复杂类型的json转换bean会出现问题,一些集合Map,List的转换出现问题。
Jackson对于复杂类型的bean转换Json,转换的json格式不是标准的Json格式
2、Google的Gson
Gson是目前功能最全的Json解析神器,Gson当初是为因应Google公司内部需求而由Google自行研发而来,
但自从在2008年五月公开发布第一版后已被许多公司或用户应用。
Gson的应用主要为toJson与fromJson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在JDK上。
而在使用这种对象转换之前需先创建好对象的类型以及其成员才能成功的将JSON字符串成功转换成相对应的对象。
类里面只要有get和set方法,Gson完全可以将复杂类型的json到bean或bean到json的转换,是JSON解析的神器。
Gson在功能上面无可挑剔,但是性能上面比FastJson有所差距。
3、阿里巴巴的FastJson
Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。
无依赖,不需要例外额外的jar,能够直接跑在JDK上。
FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。
FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库。
综上几种Json技术的比较,在项目选型的时候可以使用Google的Gson和阿里巴巴的FastJson两种并行使用,
如果只是功能要求,没有性能要求,可以使用google的Gson,
如果有性能上面的要求可以使用Gson将bean转换json确保数据的正确,使用FastJson将Json转换Bean。
跨语言的序列化方案:
json体积太大,并且缺少类型信息,实际上只用在RESTful接口上,并没有看到RPC框架会默认选json做序列化的。
国内一些大公司的使用情况:
protobuf ,腾迅,百度等
thrift,小米,美团等
hessian, 阿里用的是自己维护的版本,有js/cpp的实现,因为阿里主用java,更多是历史原因。
protobuf并不是完美解决方案
在protobuf出来以后,也不断出现新的方案。比如
https://github.com/capnproto/capnproto
https://github.com/google/flatbuffers
protobuf的一些缺点:
缺少map/set的支持(proto3支持map)
Varint编码会消耗CPU
会影响CPU缓存,比如比较大的int32从4字节用Varint表示是5字节就不对齐了
解码时要复制一份内存,不能做原地内存引用的优化
protobuf在google 2008年公开的,内部使用自然更早。当时带宽还比较昂贵,现在人们对速度的关注胜过带宽了。
protobuf需要生成代码的确有点麻烦,所以会有基于java annotation的方案:
https://github.com/protostuff/protostuff
同样thrift有:https://github.com/facebookarchive/swift
序列化方法场景推荐:
如果不使用IDL的服务间传输的话,建议使用 Protostuff Serializer ,如果有可读性要求或是基于Ajax和移动APP通信的话就使用 JSON Serializer。
一、总结在几者之间选择的考量:
1、如果你不需要很多语言相互调用, 希望保持清晰的 java 接口代码(无任何业务不相关的接口继承和方法,属性定义),减少开放工作量,推荐 hessian。
2、如果你的系统之间传输的数据量不是很大(<2M都不算大), 推荐 hessian。
3、如果需要支持大数据量的传输,多语言调用,极高的并发支持,推荐使用 thrift/protocol buffer。 通常我们并发很难超过1000 req/s,如果超过1000 req/s,在国内互联网排名绝对前5,那么恭喜你。因此一般而言,用 hessian 就够了。
二、总结
应该重视反序列化漏洞,毕竟Oracle都不得不考虑把java序列化废弃了
序列化漏洞的根本原因是:没有控制序列化的类型范围
防止序列化漏洞,最好是使用白名单
protobuf通过IDL生成代码,严格控制了类型范围
protobuf不是完美的方案,但是作为跨语言的序列化事实方案之一,IDL生成代码比较麻烦也不是啥大问题