啥是序列化?
序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。
为啥要序列化?
1、以某种存储形式使自定义对象持久化;
2、将对象从一个地方传递到另一个地方。3、使程序更具维护性
以上摘自百度百科。
一般的,在做网络服务架构的时候,需要同步数据,为了保证数据的可用性,在传输数据之前需要对数据进行序列化的操作。对于多种服务之间的数据传输,涉及到了几个会影响架构选择的问题:
- 效率
- 接口的耦合性(即一台服务器升级了接口,其它服务器是否需要执行同步升级,旧的服务器是否能够兼容升级的数据接口)
- 语言的扩展性
- 数据结构的支持
效率
一般对于网络服务来说,效率是一个非常重要的衡量因素。因此,需要细致的考量该问题。关于效率对比,在网上有很多的数据,在这里,笔者还是做了简单的测试。
接口的耦合性
关于接口的耦合性,在这里只对thrift和Protocol Buffers进行说明,因为msgpack确定是耦合的。如果服务端和客户端的接口定义不一致,必定造成读写错误,这里对msgpack就不再赘述。
- thrift ☆☆☆
为了测试增加了接口是否仍然可用,笔者写了如下测试代码:
以上的是thrift的定义文件,假定Person是老接口,Student系列是升级的几个接口。struct Person{ 1:i64 id, 2:string name } struct Student{ 1:i64 id, 2:string name, 3:string school } struct Student2{ 1:i64 id, 2:string school, 3:string name } struct Student3{ 1:i64 id, 2:double fee = 10000.0, 3:string school, 4:string name }
进行序列化和反序列化的代码如下:
using apache::thrift::transport::TMemoryBuffer; using apache::thrift::protocol::TBinaryProtocol; using boost::shared_ptr; shared_ptr<TMemoryBuffer> strBuffer(new TMemoryBuffer()); shared_ptr<TBinaryProtocol> binaryProtcol(new TBinaryProtocol(strBuffer)); Student3 a; a.id = 10; a.name ="holla back a"; a.school = "pku"; a.write(binaryProtcol.get()); std::string serialized = strBuffer->getBufferAsString(); shared_ptr<TMemoryBuffer> strBuffer2(new TMemoryBuffer()); shared_ptr<TBinaryProtocol> binaryProtcol2(new TBinaryProtocol(strBuffer2)); strBuffer2->resetBuffer((uint8_t*)serialized.data(), serialized.length()); Person a2; a2.read(binaryProtcol2.get());
如上是核心的测试代码,测试方法为发送不同的Student数据,查看收到的person数据是否正常。
测试结果如下:
Student和person可以完全实现传输;Student2传给person之后,person的name字段对应到了Student2的school字段;Student3传输给person之后,name字段为空(对应的位置上为double)。
根据以上的测试结果得出结论:
当且仅当不改变原有接口数据顺序以及类型的前提下,通过在结构的后端增加数据,不影响两端的通信。
至于原理,可以查看产生代码的read以及write方法的源代码,此文档中也有一些探讨 http://www.cnblogs.com/egmkang/archive/2011/05/14/2046335.html
P.S. thrift支持嵌套的数据类型结构,例如,一个新的数据类型可以定义如下:
struct Company{ 1:i64 id, 2:string name, 3:list<i64>ids, 4:set<i64>iSet, 5:map<i64, string> iMap, 6:Student s//OK }
- Protocol Buffers ☆☆☆☆☆
由于protocol buf 中存在required,optional,以及repeated字段,所以,protocol buf是接口耦合性最低的一种序列化方式。
语言扩展性
- thrift ☆☆☆☆☆
不多说了,敲下thrift命令,啥都支持啊。。。Available generators (and options): as3 (AS3): bindable: Add [bindable] metadata to all the struct classes. c_glib (C, using GLib): cocoa (Cocoa): log_unexpected: Log every time an unexpected field ID or type is encountered. cpp (C++): cob_style: Generate "Continuation OBject"-style classes. no_client_completion: Omit calls to completion__() in CobClient class. templates: Generate templatized reader/writer methods. pure_enums: Generate pure enums instead of wrapper classes. dense: Generate type specifications for the dense protocol. include_prefix: Use full include paths in generated files. csharp (C#): delphi (delphi): ansistr_binary: Use AnsiString as binary properties. erl (Erlang): go (Go): hs (Haskell): html (HTML): java (Java): beans: Members will be private, and setter methods will return void. private-members: Members will be private, but setter methods will return 'this' like usual. nocamel: Do not use CamelCase field accessors with beans. hashcode: Generate quality hashCode methods. android_legacy: Do not use java.io.IOException(throwable) (available for Android 2.3 and above). java5: Generate Java 1.5 compliant code (includes android_legacy flag). javame (Java ME): js (Javascript): jquery: Generate jQuery compatible code. node: Generate node.js compatible code. ocaml (OCaml): perl (Perl): php (PHP): inlined: Generate PHP inlined files server: Generate PHP server stubs autoload: Generate PHP with autoload oop: Generate PHP with object oriented subclasses rest: Generate PHP REST processors namespace: Generate PHP namespaces as defined in PHP >= 5.3 py (Python): new_style: Generate new-style classes. twisted: Generate Twisted-friendly RPC services. utf8strings: Encode/decode strings using utf8 in the generated code. slots: Generate code using slots for instance members. dynamic: Generate dynamic code, less code generated but slower. dynbase=CLS Derive generated classes from class CLS instead of TBase. dynexc=CLS Derive generated exceptions from CLS instead of TExceptionBase. dynimport='from foo.bar import CLS' Add an import line to generated code to find the dynbase class. rb (Ruby): st (Smalltalk): xsd (XSD): - msgpack ☆☆☆☆☆☆
ruby、python、perl、C/C++、php、C#、java、js....... 几乎没有不支持的,可以参考主页http://msgpack.org/ - protocol buffer ☆☆☆
和上述两个吓人的家伙比起来,有点拿不出手啊:java、c++ 和 python
本文探讨了序列化的重要性,通过thrift、Protocol Buffers和MsgPack三个例子进行了序列化和反序列化的对比。测试结果显示,thrift在接口顺序和类型不变的情况下能保持通信,Protocol Buffers具有较低的接口耦合性,而MsgPack具有广泛的语言支持。

2822

被折叠的 条评论
为什么被折叠?



