啥是序列化?
序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。
为啥要序列化?
1、以某种存储形式使自定义对象持久化;
2、将对象从一个地方传递到另一个地方。
3、使程序更具维护性
以上摘自百度百科。
一般的,在做网络服务架构的时候,需要同步数据,为了保证数据的可用性,在传输数据之前需要对数据进行序列化的操作。对于多种服务之间的数据传输,涉及到了几个会影响架构选择的问题:
- 效率
- 接口的耦合性(即一台服务器升级了接口,其它服务器是否需要执行同步升级,旧的服务器是否能够兼容升级的数据接口)
- 语言的扩展性
- 数据结构的支持
效率
一般对于网络服务来说,效率是一个非常重要的衡量因素。因此,需要细致的考量该问题。关于效率对比,在网上有很多的数据,在这里,笔者还是做了简单的测试。
接口的耦合性
关于接口的耦合性,在这里只对thrift和Protocol Buffers进行说明,因为msgpack确定是耦合的。如果服务端和客户端的接口定义不一致,必定造成读写错误,这里对msgpack就不再赘述。
- thrift ☆☆☆
为了测试增加了接口是否仍然可用,笔者写了如下测试代码:
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
}
以上的是thrift的定义文件,假定Person是老接口,Student系列是升级的几个接口。
进行序列化和反序列化的代码如下:
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 ☆☆☆☆☆
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):
不多说了,敲下thrift命令,啥都支持啊。。。 - msgpack ☆☆☆☆☆☆
ruby、python、perl、C/C++、php、C#、java、js....... 几乎没有不支持的,可以参考主页http://msgpack.org/ - protocol buffer ☆☆☆
和上述两个吓人的家伙比起来,有点拿不出手啊:java、c++ 和 python
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)