<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Apache Thrift 是 Facebook 實現的一種高效的、支援多種程式語言的遠端服務呼叫的框架。和其它RPC框架相比,它主要具有如下連個特點:
高效能。 它採用的是二進位制序列化,並且用的是長連線。比傳統的使用XML,SOAP,JSON等短連線的解決方案要快得多。
多語言支援。 它對提供了對C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk等多種常用語言的支援
正因為如此,Thrift對於高並行、巨量資料量和多語言的環境是非常有優勢的,本文就簡單的介紹一下如何使用它。
使用Thrift和傳統的Corba之類的RPC框架並無太大差異,主要分為如下三個部分:
使用IDL定義提供的服務:主要用於服務介面和資料傳輸物件(DTO)並且有一套自己的語法, Thrift中命名為thirft檔案,並且有一套自己的語法。
將IDL編譯成框架程式碼
使用者端使用框架程式碼呼叫遠端服務
伺服器端使用框架程式碼實現介面,並提供服務
和傳統RPC框架一樣,Thrift框架提供資料傳輸的服務,伺服器端和使用者端只需要關注業務即可;這一系列流程並沒有多大新穎的地方。
需要在Thrift官網下載兩個檔案:
IDL編譯工具。官方本身提供了Windows的exe版本:thrift-0.9.2.tar.gz
Thrift類庫。Thrift底層框架,提供了底層的資料傳輸服務。
下載完後,由於Thrift類庫是以原始碼形式提供的,因此需要自己編譯。為了簡單,這裡以C#為例,開啟 "libcsharpsrcThrift.sln" 工程檔案,直接編譯即可生成Thrift.dll檔案。官方說.net版本.net 3.5及以上即可。
Thrift本身提供了多多種語言的支援,這裡範例專案仍以官網的CSharp Tutorial為例來介紹一下如何在C#中使用Thrift。
首先下載介面定義檔案 tutorial.thrift 和shared.thrift 。官方的檔案中加了一大堆註釋,實際上還是比較簡單的,主體部分如下:
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() }
主要就是定義了一個這樣的介面,提供了四個介面。以及一些相關的結構體的定義。定義好介面後,呼叫Thrift.exe將其編譯成C#的程式碼:
thrift -r --gen csharp tutorial.thrift
編譯完後,會生成一個gen-csharp資料夾,裡面就是相關的結構體和介面的定義,和一些框架的實現,具體的後續再講。這個資料夾裡的檔案大部分都是伺服器端和使用者端都要用的,為了簡單起見,大可以建立一個ShareProject(低版本的VS不支援的話可以建立一個獨立的類庫專案),以方便使用者端和伺服器端參照。
首先還是來看看使用者端程式碼(執行這段程式碼需要加上前面編譯的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); }
主要就設計到了三個類:TTransport、TProtocol和Calculator.Client,其中TTransport、Tprotocol是用於傳輸控制的,和業務無關,是在Thrift.dll中定義的。而Calculator.Client則是使用者端的Proxy,用於執行RPC,和業務相關,是由idl檔案編譯生成。使用者端無需編寫程式碼,即可擁有RPC能力。(這個特效基本上所有RPC框架都具有)
伺服器端範例程式碼如下:
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."); } } }
官方程式碼基本上包括兩個部分:介面實現和服務的啟動,簡化後如下:
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() { } }
介面實現依賴於IDL生成的Calculator.Iface介面,這裡我就實現了一個add介面。再來看看伺服器端
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(); }
伺服器端主要的功能就是將剛才的介面作為服務載入起來,並啟動服務,也是比較常規的做法,沒有太多需要介紹的地方
從這個Demo來看,主要過程和其它RPC框架的流程倒也沒有太大區別。一個比較出彩的地方是Thrift是提供了原生的.net執行庫的(前面編譯的Thrift.dll),作為一個跨語言的框架不用Pinvoke非常給力,給部署帶來不少方便。本來高效能才是它的主要特點,後續有空再測試一下。
最後,本文只是一個簡單的入門體驗,如果需要更多資訊,請參看Thrift的官方網站。
到此這篇關於C#使用遠端服務呼叫框架Apache Thrift的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45