Thrift架構~windows下安裝(zhuang)和(he)Hello World及(ji)編(bian)碼引(yin)起的錯誤
最(zui)近開始正(zheng)式接觸Thrift架構,很(hen)牛B的技術,它被apache收納了,屬于開源中(zhong)的一員,呵呵。
概念:
Thrift源于(yu)大(da)名鼎(ding)(ding)鼎(ding)(ding)的(de)(de)(de)(de)facebook之手,在2007年facebook提(ti)交(jiao)Apache基金會將Thrift作為(wei)一(yi)個開(kai)源項(xiang)目,對(dui)于(yu)當(dang)時 的(de)(de)(de)(de)facebook來說創(chuang)造thrift是(shi)(shi)為(wei)了解決(jue)facebook系(xi)統(tong)中(zhong)各(ge)系(xi)統(tong)間(jian)大(da)數(shu)(shu)據(ju)(ju)量的(de)(de)(de)(de)傳(chuan) 輸通(tong)(tong)信以(yi)及系(xi)統(tong)之間(jian)語言(yan)環境不同需(xu)要跨平臺的(de)(de)(de)(de)特性。所(suo)以(yi)thrift可(ke)以(yi)支(zhi)持(chi)多種(zhong)(zhong)程(cheng)序(xu)語言(yan),例如: C++, C#, Cocoa, Erlang, Haskell, Java, Ocami, Perl, PHP, Python, Ruby, Smalltalk. 在多種(zhong)(zhong)不同的(de)(de)(de)(de)語言(yan)之間(jian)通(tong)(tong)信thrift可(ke)以(yi)作為(wei)二(er)進(jin)制的(de)(de)(de)(de)高性能的(de)(de)(de)(de)通(tong)(tong)訊(xun)中(zhong)間(jian)件,支(zhi)持(chi)數(shu)(shu)據(ju)(ju)(對(dui)象)序(xu)列化(hua)和多種(zhong)(zhong)類(lei)型(xing)的(de)(de)(de)(de)RPC服(fu)務(wu)。Thrift適用于(yu)程(cheng)序(xu)對(dui)程(cheng) 序(xu)靜態的(de)(de)(de)(de)數(shu)(shu)據(ju)(ju)交(jiao)換,需(xu)要先(xian)確定好他(ta)(ta)的(de)(de)(de)(de)數(shu)(shu)據(ju)(ju)結構,他(ta)(ta)是(shi)(shi)完全靜態化(hua)的(de)(de)(de)(de),當(dang)數(shu)(shu)據(ju)(ju)結構發生變化(hua)時,必須重新(xin)編(bian)輯IDL文件,代(dai)碼生成,再編(bian)譯載入(ru)的(de)(de)(de)(de)流程(cheng),跟其他(ta)(ta) IDL工具相(xiang)(xiang)比較可(ke)以(yi)視為(wei)是(shi)(shi)Thrift的(de)(de)(de)(de)弱項(xiang),Thrift適用于(yu)搭建大(da)型(xing)數(shu)(shu)據(ju)(ju)交(jiao)換及存儲的(de)(de)(de)(de)通(tong)(tong)用工具,對(dui)于(yu)大(da)型(xing)系(xi)統(tong)中(zhong)的(de)(de)(de)(de)內部數(shu)(shu)據(ju)(ju)傳(chuan)輸相(xiang)(xiang)對(dui)于(yu)JSON和 xml無論在性能、傳(chuan)輸大(da)小上有明(ming)顯的(de)(de)(de)(de)優勢。
下面看一下windows下的安裝與使用。
Thrift目前最(zui)高(gao)0.9.1,地址:
注意,我(wo)們要把exe和tar文(wen)件都下載下來,exe用來編(bian)譯(yi)你(ni)的thrift中間(jian)語言,而tar解壓(ya)后,我(wo)們可以看(kan)到csharp,php,java,js等多種開發語言的實例代(dai)碼,對我(wo)們很(hen)有幫(bang)助(zhu)的,
下載之后,我們把(ba)exe文(wen)件可以(yi)放在(zai)C盤,建個Thrift目錄,把(ba)它放入,然后可以(yi)配置一(yi)下環境變量,如圖:
然(ran)后,我們就(jiu)可以進(jin)行(xing)thrift中(zhong)間語言的(de)(de)開發(fa)了,之(zhi)所以說它(ta)(ta)是(shi)中(zhong)間語言,是(shi)因為(wei)它(ta)(ta)不是(shi)最終我們要使用的(de)(de),而需要將它(ta)(ta)進(jin)行(xing)編譯(yi)之(zhi)后,才生成(cheng)我們的(de)(de)目(mu)標語言,就(jiu)像C語言,它(ta)(ta)在(zai)編譯(yi)時也是(shi)生成(cheng)obj目(mu)標語言,然(ran)后再二次編譯(yi)最終生成(cheng)exe文件,它(ta)(ta)們的(de)(de)道理是(shi)一樣的(de)(de),
我們的thrift語言(yan),通過(guo)thrift程(cheng)序可以生成多(duo)種編程(cheng)語言(yan)的源代碼。
編碼問題
使用VS建立一個thrift文件(jian)后(hou)(hou),在進行編(bian)譯時(shi)出現了問題(ti),最后(hou)(hou)找到(dao)答案,原來(lai)是(shi)編(bian)碼問題(ti),最后(hou)(hou)使用記(ji)事本把編(bian)碼被為ANSI就可以正(zheng)常編(bian)譯了。
Hello world程序代碼:
namespace csharp HelloThriftspace exception Xception { 1: i32 errorCode, 2: string message } service HelloThrift{ void HelloWorld() throws (1:Xception ex) }
編譯代碼:
thrift --gen csharp hellothrift.thrift
結果:namespace表(biao)示文件(jian)夾的所(suo)在(zai)(zai)地,方(fang)法,結構,枚(mei)舉都是(shi)以文件(jian)形式存(cun)在(zai)(zai)的
生成的C#代碼:
Xception.cs
namespace HelloThriftspace { #if !SILVERLIGHT [Serializable] #endif public partial class Xception : TException, TBase { private int _errorCode; private string _message; public int ErrorCode { get { return _errorCode; } set { __isset.errorCode = true; this._errorCode = value; } } public string Message { get { return _message; } set { __isset.message = true; this._message = value; } } public Isset __isset; #if !SILVERLIGHT [Serializable] #endif public struct Isset { public bool errorCode; public bool message; } public Xception() { } 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) { ErrorCode = iprot.ReadI32(); } else { TProtocolUtil.Skip(iprot, field.Type); } break; case 2: if (field.Type == TType.String) { Message = 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("Xception"); oprot.WriteStructBegin(struc); TField field = new TField(); if (__isset.errorCode) { field.Name = "errorCode"; field.Type = TType.I32; field.ID = 1; oprot.WriteFieldBegin(field); oprot.WriteI32(ErrorCode); oprot.WriteFieldEnd(); } if (Message != null && __isset.message) { field.Name = "message"; field.Type = TType.String; field.ID = 2; oprot.WriteFieldBegin(field); oprot.WriteString(Message); oprot.WriteFieldEnd(); } oprot.WriteFieldStop(); oprot.WriteStructEnd(); } public override string ToString() { StringBuilder sb = new StringBuilder("Xception("); sb.Append("ErrorCode: "); sb.Append(ErrorCode); sb.Append(",Message: "); sb.Append(Message); sb.Append(")"); return sb.ToString(); } } }
HelloThrift.cs
namespace HelloThriftspace { public partial class HelloThrift { public interface Iface { void HelloWorld(); #if SILVERLIGHT IAsyncResult Begin_HelloWorld(AsyncCallback callback, object state); void End_HelloWorld(IAsyncResult asyncResult); #endif } public class Client : IDisposable, Iface { public Client(TProtocol prot) : this(prot, prot) { } public Client(TProtocol iprot, TProtocol oprot) { iprot_ = iprot; oprot_ = oprot; } protected TProtocol iprot_; protected TProtocol oprot_; protected int seqid_; public TProtocol InputProtocol { get { return iprot_; } } public TProtocol OutputProtocol { get { return oprot_; } } #region " IDisposable Support " private bool _IsDisposed; // IDisposable public void Dispose() { Dispose(true); } protected virtual void Dispose(bool disposing) { if (!_IsDisposed) { if (disposing) { if (iprot_ != null) { ((IDisposable)iprot_).Dispose(); } if (oprot_ != null) { ((IDisposable)oprot_).Dispose(); } } } _IsDisposed = true; } #endregion #if SILVERLIGHT public IAsyncResult Begin_HelloWorld(AsyncCallback callback, object state) { return send_HelloWorld(callback, state); } public void End_HelloWorld(IAsyncResult asyncResult) { oprot_.Transport.EndFlush(asyncResult); recv_HelloWorld(); } #endif public void HelloWorld() { #if !SILVERLIGHT send_HelloWorld(); recv_HelloWorld(); #else var asyncResult = Begin_HelloWorld(null, null); End_HelloWorld(asyncResult); #endif } #if SILVERLIGHT public IAsyncResult send_HelloWorld(AsyncCallback callback, object state) #else public void send_HelloWorld() #endif { oprot_.WriteMessageBegin(new TMessage("HelloWorld", TMessageType.Call, seqid_)); HelloWorld_args args = new HelloWorld_args(); args.Write(oprot_); oprot_.WriteMessageEnd(); #if SILVERLIGHT return oprot_.Transport.BeginFlush(callback, state); #else oprot_.Transport.Flush(); #endif } public void recv_HelloWorld() { TMessage msg = iprot_.ReadMessageBegin(); if (msg.Type == TMessageType.Exception) { TApplicationException x = TApplicationException.Read(iprot_); iprot_.ReadMessageEnd(); throw x; } HelloWorld_result result = new HelloWorld_result(); result.Read(iprot_); iprot_.ReadMessageEnd(); if (result.__isset.ex) { throw result.Ex; } return; } } public class Processor : TProcessor { public Processor(Iface iface) { iface_ = iface; processMap_["HelloWorld"] = HelloWorld_Process; } protected delegate void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot); private Iface iface_; protected Dictionary<string, ProcessFunction> processMap_ = new Dictionary<string, ProcessFunction>(); public bool Process(TProtocol iprot, TProtocol oprot) { try { TMessage msg = iprot.ReadMessageBegin(); ProcessFunction fn; processMap_.TryGetValue(msg.Name, out fn); if (fn == null) { TProtocolUtil.Skip(iprot, TType.Struct); iprot.ReadMessageEnd(); TApplicationException x = new TApplicationException (TApplicationException.ExceptionType.UnknownMethod, "Invalid method name: '" + msg.Name + "'"); oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID)); x.Write(oprot); oprot.WriteMessageEnd(); oprot.Transport.Flush(); return true; } fn(msg.SeqID, iprot, oprot); } catch (IOException) { return false; } return true; } public void HelloWorld_Process(int seqid, TProtocol iprot, TProtocol oprot) { HelloWorld_args args = new HelloWorld_args(); args.Read(iprot); iprot.ReadMessageEnd(); HelloWorld_result result = new HelloWorld_result(); try { iface_.HelloWorld(); } catch (Xception ex) { result.Ex = ex; } oprot.WriteMessageBegin(new TMessage("HelloWorld", TMessageType.Reply, seqid)); result.Write(oprot); oprot.WriteMessageEnd(); oprot.Transport.Flush(); } } #if !SILVERLIGHT [Serializable] #endif public partial class HelloWorld_args : TBase { public HelloWorld_args() { } public void Read (TProtocol iprot) { TField field; iprot.ReadStructBegin(); while (true) { field = iprot.ReadFieldBegin(); if (field.Type == TType.Stop) { break; } switch (field.ID) { default: TProtocolUtil.Skip(iprot, field.Type); break; } iprot.ReadFieldEnd(); } iprot.ReadStructEnd(); } public void Write(TProtocol oprot) { TStruct struc = new TStruct("HelloWorld_args"); oprot.WriteStructBegin(struc); oprot.WriteFieldStop(); oprot.WriteStructEnd(); } public override string ToString() { StringBuilder sb = new StringBuilder("HelloWorld_args("); sb.Append(")"); return sb.ToString(); } } #if !SILVERLIGHT [Serializable] #endif public partial class HelloWorld_result : TBase { private Xception _ex; public Xception Ex { get { return _ex; } set { __isset.ex = true; this._ex = value; } } public Isset __isset; #if !SILVERLIGHT [Serializable] #endif public struct Isset { public bool ex; } public HelloWorld_result() { } 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.Struct) { Ex = new Xception(); Ex.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("HelloWorld_result"); oprot.WriteStructBegin(struc); TField field = new TField(); if (this.__isset.ex) { if (Ex != null) { field.Name = "Ex"; field.Type = TType.Struct; field.ID = 1; oprot.WriteFieldBegin(field); Ex.Write(oprot); oprot.WriteFieldEnd(); } } oprot.WriteFieldStop(); oprot.WriteStructEnd(); } public override string ToString() { StringBuilder sb = new StringBuilder("HelloWorld_result("); sb.Append("Ex: "); sb.Append(Ex== null ? "<null>" : Ex.ToString()); sb.Append(")"); return sb.ToString(); } } } }
感覺(jue)生成的代(dai)碼還是比較麻煩(fan)的,希望thrift在以后的產(chan)品中,對這塊解決的好一(yi)點,呵呵。
下一講我(wo)們將進行客戶端與服務器環境的搭建。