设为首页 收藏本站
查看: 1826|回复: 0

[经验分享] 序列化之Apache Thrift

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-7-31 12:48:55 | 显示全部楼层 |阅读模式
  Apache Thrift和ProtoBuf一样,都是为优化序列化而生,Thrift是一个通信框架,最初有FaceBook开发,后交由Apache管理,目前Facebook也在使用。Thrift与ProtoBuf同样是跨平台多语言的,不过Thrift几乎支持现下的所有流行的语言,而ProtoBuf.net是.net的移植,相比而来Thrift支持更广。我这里做的是对Thrift序列化数据在效率做实验
  1.定义接口文件
  相当于数据契约。Thrift的契约定义用了自己的一套语法(IDL),这样做的目的是让他可以跨语言,同一套契约可以在任何语言下使用,关于IDL方法可以去参考Thrift的白皮书。
  和上一篇文章相同,有以下这样两个类

public class Person
{
public int Id { get; set; }]
public string Name { get; set; }
public Address Address { get; set; }
}

public class Address
{
public string Line1 { get; set; }
public string Line2 { get; set; }
}
  用Thrift 的IDL语言定义后如下,文件保存为test.idl


struct Address
{
1: string Line1,
2: string Line2
}
struct Person
{
1: i32 Id,
2: string Name,
3: Address Address
}
  2. 使用Thrift提供的windows编译器生成文件
  使用thrift-0.9.1.exe生成文件,将test.idl与thrift-0.9.1.exe放在同级目录下,在控制台是执行命令


thrift-0.9.1 --gen csharp test.idl  文件生成在目录下的gen-csharp文件夹中
  

DSC0000.gif DSC0001.gif Address.cs/**
* Autogenerated by Thrift Compiler (0.9.1)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
*  @generated
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Thrift;
using Thrift.Collections;
using System.Runtime.Serialization;
using Thrift.Protocol;
using Thrift.Transport;

#if !SILVERLIGHT
[Serializable]
#endif
public partial class Address : TBase
{
private string _Line1;
private string _Line2;
public string Line1
{
get
{
return _Line1;
}
set
{
__isset.Line1 = true;
this._Line1 = value;
}
}
public string Line2
{
get
{
return _Line2;
}
set
{
__isset.Line2 = true;
this._Line2 = value;
}
}

public Isset __isset;
#if !SILVERLIGHT
[Serializable]
#endif
public struct Isset {
public bool Line1;
public bool Line2;
}
public Address() {
}
public void Read (TProtocol iprot)
{
TField field;
iprot.ReadStructBegin();
while (true)
{
field = iprot.ReadFieldBegin();
if (field.Type == TType.Stop) {
break;
}
switch (field.ID)
{
case 1:
if (field.Type == TType.String) {
Line1 = iprot.ReadString();
} else {
TProtocolUtil.Skip(iprot, field.Type);
}
break;
case 2:
if (field.Type == TType.String) {
Line2 = iprot.ReadString();
} else {
TProtocolUtil.Skip(iprot, field.Type);
}
break;
default:
TProtocolUtil.Skip(iprot, field.Type);
break;
}
iprot.ReadFieldEnd();
}
iprot.ReadStructEnd();
}
public void Write(TProtocol oprot) {
TStruct struc = new TStruct("Address");
oprot.WriteStructBegin(struc);
TField field = new TField();
if (Line1 != null && __isset.Line1) {
field.Name = "Line1";
field.Type = TType.String;
field.ID = 1;
oprot.WriteFieldBegin(field);
oprot.WriteString(Line1);
oprot.WriteFieldEnd();
}
if (Line2 != null && __isset.Line2) {
field.Name = "Line2";
field.Type = TType.String;
field.ID = 2;
oprot.WriteFieldBegin(field);
oprot.WriteString(Line2);
oprot.WriteFieldEnd();
}
oprot.WriteFieldStop();
oprot.WriteStructEnd();
}
public override string ToString() {
StringBuilder sb = new StringBuilder("Address(");
sb.Append("Line1: ");
sb.Append(Line1);
sb.Append(",Line2: ");
sb.Append(Line2);
sb.Append(")");
return sb.ToString();
}
}



Person.cs/**
* Autogenerated by Thrift Compiler (0.9.1)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
*  @generated
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Thrift;
using Thrift.Collections;
using System.Runtime.Serialization;
using Thrift.Protocol;
using Thrift.Transport;

#if !SILVERLIGHT
[Serializable]
#endif
public partial class Person : TBase
{
private int _Id;
private string _Name;
private Address _Address;
public int Id
{
get
{
return _Id;
}
set
{
__isset.Id = true;
this._Id = value;
}
}
public string Name
{
get
{
return _Name;
}
set
{
__isset.Name = true;
this._Name = value;
}
}
public Address Address
{
get
{
return _Address;
}
set
{
__isset.Address = true;
this._Address = value;
}
}

public Isset __isset;
#if !SILVERLIGHT
[Serializable]
#endif
public struct Isset {
public bool Id;
public bool Name;
public bool Address;
}
public Person() {
}
public void Read (TProtocol iprot)
{
TField field;
iprot.ReadStructBegin();
while (true)
{
field = iprot.ReadFieldBegin();
if (field.Type == TType.Stop) {
break;
}
switch (field.ID)
{
case 1:
if (field.Type == TType.I32) {
Id = iprot.ReadI32();
} else {
TProtocolUtil.Skip(iprot, field.Type);
}
break;
case 2:
if (field.Type == TType.String) {
Name = iprot.ReadString();
} else {
TProtocolUtil.Skip(iprot, field.Type);
}
break;
case 3:
if (field.Type == TType.Struct) {
Address = new Address();
Address.Read(iprot);
} else {
TProtocolUtil.Skip(iprot, field.Type);
}
break;
default:
TProtocolUtil.Skip(iprot, field.Type);
break;
}
iprot.ReadFieldEnd();
}
iprot.ReadStructEnd();
}
public void Write(TProtocol oprot) {
TStruct struc = new TStruct("Person");
oprot.WriteStructBegin(struc);
TField field = new TField();
if (__isset.Id) {
field.Name = "Id";
field.Type = TType.I32;
field.ID = 1;
oprot.WriteFieldBegin(field);
oprot.WriteI32(Id);
oprot.WriteFieldEnd();
}
if (Name != null && __isset.Name) {
field.Name = "Name";
field.Type = TType.String;
field.ID = 2;
oprot.WriteFieldBegin(field);
oprot.WriteString(Name);
oprot.WriteFieldEnd();
}
if (Address != null && __isset.Address) {
field.Name = "Address";
field.Type = TType.Struct;
field.ID = 3;
oprot.WriteFieldBegin(field);
Address.Write(oprot);
oprot.WriteFieldEnd();
}
oprot.WriteFieldStop();
oprot.WriteStructEnd();
}
public override string ToString() {
StringBuilder sb = new StringBuilder("Person(");
sb.Append("Id: ");
sb.Append(Id);
sb.Append(",Name: ");
sb.Append(Name);
sb.Append(",Address: ");
sb.Append(Address== null ? "" : Address.ToString());
sb.Append(")");
return sb.ToString();
}
}

  
  3. 添加Thrift.dll
  下载thrift-0.9.1.tar.gz解压后找到对应的C#代码编译后就得到Thrift.dll了
   DSC0002.png
  4. 序列化数据
  创建一个C#控制台应用程序,将生成的两个代码文件添加到项目中,再添加Thrift.dll引用,和上次一样序列化同样的1000条数据,得到的数据大小为48.7 KB (49,890 字节)


    class Program
{
static void Main(string[] args)
{
Person person = new Person { Address = new Address { Line1 = "Line1", Line2 = "Line2" }, Id = 1, Name = "Name" };
using (System.IO.Stream stream = System.IO.File.Create("Person.dat"))
{
Thrift.Transport.TTransport transport = new Thrift.Transport.TStreamTransport(null,stream);
Thrift.Protocol.TProtocol protocol = new Thrift.Protocol.TBinaryProtocol(transport);
List list = new List();
for (int i = 0; i < 1000; i++)
{
Person item = new Person { Address = new Address { Line1 = "Line1", Line2 = "Line2" }, Id = i, Name = "Name" + i };
item.Write(protocol);
}
}
}
}
  Demo下载
  对比上次的ProtoBuf大了不少,和C#的原始二进制序列化只差5kb。当然我这次对比几个数据也不能说明什么问题,只能做个大概了解。网络通信是个复杂的过程。序列化数据大小直接影响网络带宽,序列化与反序列化的效率也直接影响着服务器资源。当数据量大小上升到不同数量级时ProtoBuf和Thrift到底谁更占上风我就法验证了。
  Thrift是个网络通信框架,提供了多种数据序列化方式,并且支持多种语言,通过Thrift的IDL语言定义过的契约可以在所有支持的语言上使用,且与平台无关,这就是他NB的地方。从Thrift的Tutorial看来对现将通信协议迁移也不是件事。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-92752-1-1.html 上篇帖子: spring的DriverManagerDataSource与apache的BasicDataSource(转) 下篇帖子: 本地搭建 Apache 服务器
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表