C#使用遠程服務調用框架Apache Thrift
Apache Thrift 是 Facebook 實現(xiàn)的一種高效的、支持多種編程語言的遠程服務調用的框架。和其它RPC框架相比,它主要具有如下連個特點:
高性能。 它采用的是二進制序列化,并且用的是長連接。比傳統(tǒng)的使用XML,SOAP,JSON等短連接的解決方案要快得多。
多語言支持。 它對提供了對C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk等多種常用語言的支持
正因為如此,Thrift對于高并發(fā)、大數(shù)據(jù)量和多語言的環(huán)境是非常有優(yōu)勢的,本文就簡單的介紹一下如何使用它。
使用Thrift和傳統(tǒng)的Corba之類的RPC框架并無太大差異,主要分為如下三個部分:
使用IDL定義提供的服務:主要用于服務接口和數(shù)據(jù)傳輸對象(DTO)并且有一套自己的語法, Thrift中命名為thirft文件,并且有一套自己的語法。
將IDL編譯成框架代碼
客戶端使用框架代碼調用遠程服務
服務端使用框架代碼實現(xiàn)接口,并提供服務
和傳統(tǒng)RPC框架一樣,Thrift框架提供數(shù)據(jù)傳輸?shù)姆?,服務端和客戶端只需要關注業(yè)務即可;這一系列流程并沒有多大新穎的地方。
準備工作:
需要在Thrift官網(wǎng)下載兩個文件:
IDL編譯工具。官方本身提供了Windows的exe版本:thrift-0.9.2.tar.gz
Thrift類庫。Thrift底層框架,提供了底層的數(shù)據(jù)傳輸服務。
下載完后,由于Thrift類庫是以源碼形式提供的,因此需要自己編譯。為了簡單,這里以C#為例,打開 "\lib\csharp\src\Thrift.sln" 工程文件,直接編譯即可生成Thrift.dll文件。官方說.net版本.net 3.5及以上即可。
示例項目:
Thrift本身提供了多多種語言的支持,這里示例項目仍以官網(wǎng)的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文件夾,里面就是相關的結構體和接口的定義,和一些框架的實現(xiàn),具體的后續(xù)再講。這個文件夾里的文件大部分都是服務端和客戶端都要用的,為了簡單起見,大可以建立一個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是用于傳輸控制的,和業(yè)務無關,是在Thrift.dll中定義的。而Calculator.Client則是客戶端的Proxy,用于執(zhí)行RPC,和業(yè)務相關,是由idl文件編譯生成??蛻舳藷o需編寫代碼,即可擁有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.");
}
}
}官方代碼基本上包括兩個部分:接口實現(xiàn)和服務的啟動,簡化后如下:
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()
{
}
}接口實現(xiàn)依賴于IDL生成的Calculator.Iface接口,這里我就實現(xiàn)了一個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();
}服務端主要的功能就是將剛才的接口作為服務加載起來,并啟動服務,也是比較常規(guī)的做法,沒有太多需要介紹的地方
從這個Demo來看,主要過程和其它RPC框架的流程倒也沒有太大區(qū)別。一個比較出彩的地方是Thrift是提供了原生的.net運行庫的(前面編譯的Thrift.dll),作為一個跨語言的框架不用Pinvoke非常給力,給部署帶來不少方便。本來高性能才是它的主要特點,后續(xù)有空再測試一下。
最后,本文只是一個簡單的入門體驗,如果需要更多信息,請參看Thrift的官方網(wǎng)站。
到此這篇關于C#使用遠程服務調用框架Apache Thrift的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
C#使用PPT組件的CreateVideo方法實現(xiàn)視頻生成
這篇文章主要為大家詳細介紹了C#如何使用PPT組件的CreateVideo方法實現(xiàn)視頻生成,文中的示例代碼講解詳細,有需要的小伙伴可以跟隨小編一起學習一下2023-10-10
C#基礎教程之IComparable用法,實現(xiàn)List<T>.sort()排序
這篇文章主要介紹了C#的一些基礎知識,主要是IComparable用法,實現(xiàn)List<T>.sort()排序,非常的實用,這里推薦給大家。2015-02-02

