您好,登錄后才能下訂單哦!
這篇“C#怎么使用遠(yuǎn)程服務(wù)調(diào)用框架Apache Thrift”文章的知識點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“C#怎么使用遠(yuǎn)程服務(wù)調(diào)用框架Apache Thrift”文章吧。
Apache Thrift 是 Facebook 實(shí)現(xiàn)的一種高效的、支持多種編程語言的遠(yuǎn)程服務(wù)調(diào)用的框架。和其它RPC框架相比,它主要具有如下連個特點(diǎn):
高性能。 它采用的是二進(jìn)制序列化,并且用的是長連接。比傳統(tǒng)的使用XML,SOAP,JSON等短連接的解決方案要快得多。
多語言支持。 它對提供了對C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk等多種常用語言的支持
正因?yàn)槿绱?,Thrift對于高并發(fā)、大數(shù)據(jù)量和多語言的環(huán)境是非常有優(yōu)勢的,本文就簡單的介紹一下如何使用它。
使用Thrift和傳統(tǒng)的Corba之類的RPC框架并無太大差異,主要分為如下三個部分:
使用IDL定義提供的服務(wù):主要用于服務(wù)接口和數(shù)據(jù)傳輸對象(DTO)并且有一套自己的語法, Thrift中命名為thirft文件,并且有一套自己的語法。
將IDL編譯成框架代碼
客戶端使用框架代碼調(diào)用遠(yuǎn)程服務(wù)
服務(wù)端使用框架代碼實(shí)現(xiàn)接口,并提供服務(wù)
和傳統(tǒng)RPC框架一樣,Thrift框架提供數(shù)據(jù)傳輸?shù)姆?wù),服務(wù)端和客戶端只需要關(guān)注業(yè)務(wù)即可;這一系列流程并沒有多大新穎的地方。
需要在Thrift官網(wǎng)下載兩個文件:
IDL編譯工具。官方本身提供了Windows的exe版本:thrift-0.9.2.tar.gz
Thrift類庫。Thrift底層框架,提供了底層的數(shù)據(jù)傳輸服務(wù)。
下載完后,由于Thrift類庫是以源碼形式提供的,因此需要自己編譯。為了簡單,這里以C#為例,打開 "\lib\csharp\src\Thrift.sln" 工程文件,直接編譯即可生成Thrift.dll文件。官方說.net版本.net 3.5及以上即可。
Thrift本身提供了多多種語言的支持,這里示例項(xiàng)目仍以官網(wǎng)的CSharp Tutorial為例來介紹一下如何在C#中使用Thrift。
首先下載接口定義文件 tutorial.thrift 和shared.thrift 。官方的文檔中加了一大堆注釋,實(shí)際上還是比較簡單的,主體部分如下:
service Calculator extends shared.SharedService { void ping(), i32 add(1:i32 num1, 2:i32 num2), i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), oneway void zip() }
主要就是定義了一個這樣的接口,提供了四個接口。以及一些相關(guān)的結(jié)構(gòu)體的定義。定義好接口后,調(diào)用Thrift.exe將其編譯成C#的代碼:
thrift -r --gen csharp tutorial.thrift
編譯完后,會生成一個gen-csharp文件夾,里面就是相關(guān)的結(jié)構(gòu)體和接口的定義,和一些框架的實(shí)現(xiàn),具體的后續(xù)再講。這個文件夾里的文件大部分都是服務(wù)端和客戶端都要用的,為了簡單起見,大可以建立一個ShareProject(低版本的VS不支持的話可以建立一個獨(dú)立的類庫項(xiàng)目),以方便客戶端和服務(wù)端引用。
首先還是來看看客戶端代碼(運(yùn)行這段代碼需要加上前面編譯的Thrift.dll和編譯idl文件生成的一堆C#代碼):
using System; using Thrift; using Thrift.Protocol; using Thrift.Server; using Thrift.Transport; namespace CSharpTutorial { public class CSharpClient { public static void Main() { try { TTransport transport = new TSocket("localhost", 9090); TProtocol protocol = new TBinaryProtocol(transport); Calculator.Client client = new Calculator.Client(protocol); transport.Open(); try { client.ping(); Console.WriteLine("ping()"); int sum = client.add(1, 1); Console.WriteLine("1+1={0}", sum); Work work = new Work(); work.Op = Operation.DIVIDE; work.Num1 = 1; work.Num2 = 0; try { int quotient = client.calculate(1, work); Console.WriteLine("Whoa we can divide by 0"); } catch (InvalidOperation io) { Console.WriteLine("Invalid operation: " + io.Why); } work.Op = Operation.SUBTRACT; work.Num1 = 15; work.Num2 = 10; try { int diff = client.calculate(1, work); Console.WriteLine("15-10={0}", diff); } catch (InvalidOperation io) { Console.WriteLine("Invalid operation: " + io.Why); } SharedStruct log = client.getStruct(1); Console.WriteLine("Check log: {0}", log.Value); } finally { transport.Close(); } } catch (TApplicationException x) { Console.WriteLine(x.StackTrace); } } } }
官方的例子簡化一下后如下:
using (TTransport transport = new TSocket("localhost", 9090)) using (TProtocol protocol = new TBinaryProtocol(transport)) using (Calculator.Client client = new Calculator.Client(protocol)) { transport.Open(); int sum = client.add(1, 1); Console.WriteLine("1+1={0}", sum); }
主要就設(shè)計(jì)到了三個類:TTransport、TProtocol和Calculator.Client,其中TTransport、Tprotocol是用于傳輸控制的,和業(yè)務(wù)無關(guān),是在Thrift.dll中定義的。而Calculator.Client則是客戶端的Proxy,用于執(zhí)行RPC,和業(yè)務(wù)相關(guān),是由idl文件編譯生成??蛻舳藷o需編寫代碼,即可擁有RPC能力。(這個特效基本上所有RPC框架都具有)
服務(wù)端示例代碼如下:
using System; using System.Collections.Generic; using Thrift.Server; using Thrift.Transport; namespace CSharpTutorial { public class CalculatorHandler : Calculator.Iface { Dictionary<int, SharedStruct> log; public CalculatorHandler() { log = new Dictionary<int, SharedStruct>(); } public void ping() { Console.WriteLine("ping()"); } public int add(int n1, int n2) { Console.WriteLine("add({0},{1})", n1, n2); return n1 + n2; } public int calculate(int logid, Work work) { Console.WriteLine("calculate({0}, [{1},{2},{3}])", logid, work.Op, work.Num1, work.Num2); int val = 0; switch (work.Op) { case Operation.ADD: val = work.Num1 + work.Num2; break; case Operation.SUBTRACT: val = work.Num1 - work.Num2; break; case Operation.MULTIPLY: val = work.Num1 * work.Num2; break; case Operation.DIVIDE: if (work.Num2 == 0) { InvalidOperation io = new InvalidOperation(); io.What = (int)work.Op; io.Why = "Cannot divide by 0"; throw io; } val = work.Num1 / work.Num2; break; default: { InvalidOperation io = new InvalidOperation(); io.What = (int)work.Op; io.Why = "Unknown operation"; throw io; } } SharedStruct entry = new SharedStruct(); entry.Key = logid; entry.Value = val.ToString(); log[logid] = entry; return val; } public SharedStruct getStruct(int key) { Console.WriteLine("getStruct({0})", key); return log[key]; } public void zip() { Console.WriteLine("zip()"); } } public class CSharpServer { public static void Main() { try { CalculatorHandler handler = new CalculatorHandler(); Calculator.Processor processor = new Calculator.Processor(handler); TServerTransport serverTransport = new TServerSocket(9090); TServer server = new TSimpleServer(processor, serverTransport); // Use this for a multithreaded server // server = new TThreadPoolServer(processor, serverTransport); Console.WriteLine("Starting the server..."); server.Serve(); } catch (Exception x) { Console.WriteLine(x.StackTrace); } Console.WriteLine("done."); } } }
官方代碼基本上包括兩個部分:接口實(shí)現(xiàn)和服務(wù)的啟動,簡化后如下:
public class CalculatorHandler : Calculator.Iface { public void ping() { } public int add(int n1, int n2) { return n1 + n2; } public int calculate(int logid, Work work) { throw new InvalidOperation(); } public SharedStruct getStruct(int key) { return new SharedStruct(); } public void zip() { } }
接口實(shí)現(xiàn)依賴于IDL生成的Calculator.Iface接口,這里我就實(shí)現(xiàn)了一個add接口。再來看看服務(wù)端
static void Main(string[] args) { CalculatorHandler handler = new CalculatorHandler(); Calculator.Processor processor = new Calculator.Processor(handler); TServerTransport serverTransport = new TServerSocket(9090); TServer server = new TSimpleServer(processor, serverTransport); Console.WriteLine("Starting the server..."); server.Serve(); }
服務(wù)端主要的功能就是將剛才的接口作為服務(wù)加載起來,并啟動服務(wù),也是比較常規(guī)的做法,沒有太多需要介紹的地方
從這個Demo來看,主要過程和其它RPC框架的流程倒也沒有太大區(qū)別。一個比較出彩的地方是Thrift是提供了原生的.net運(yùn)行庫的(前面編譯的Thrift.dll),作為一個跨語言的框架不用Pinvoke非常給力,給部署帶來不少方便。本來高性能才是它的主要特點(diǎn),后續(xù)有空再測試一下。
以上就是關(guān)于“C#怎么使用遠(yuǎn)程服務(wù)調(diào)用框架Apache Thrift”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。