CSharp使用Thrift作為RPC框架入門(一)

楊凱2020發表於2021-11-23

前言

本文將介紹由 Facebook 開發的遠端服務呼叫框架 Apache Thrift,它採用介面描述語言定義並建立服務,支援可擴充套件的跨語言服務開發,所包含的程式碼生成引擎可以在多種語言中,如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等建立高效的、無縫的服務,其傳輸資料採用二進位制格式,相對 XML 和 JSON 體積更小,對於高併發、大資料量和多語言的環境更有優勢。本文將詳細介紹 Thrift 在C#語言下的使用方式,並且提供豐富的例項程式碼加以解釋說明,幫助使用者快速構建服務。

完善開發工具

通過nuget在vs2019中安裝thrift

在專案中引用右鍵點選管理Nuget程式包,在開啟的介面輸入thrift,如下圖:

我們選擇ApacheThrift這一項進行安裝,安裝後,在我們專案裡有Thrift45.dll的引用,如下圖:

下載thrift程式碼生成工具

thrift是支援異構語言、異構平臺的通訊開發RPC框架,它通過中間語言IDL進行描述你要定義的結構、類、服務等,並通過程式碼生成工具生成各個語言上對應的程式碼。

接下來,我們進入Apache網站Thrift專案下載Thrift程式碼生成工具,如下圖:

我們把下載的這個exe檔案放到我們專案的根目錄下,以備後用,如下圖:

至此,關於thrift的開發工具,我們已經準備完畢,接下來來編寫thrift介面描述檔案

thrift描述檔案

thrift提供的介面描述檔案是以thrift結尾的格式檔案,我們來解釋一下這種IDL的語法,

  • 它提供了基礎型別的定義,包括bool、i16、i32、i64、double、string
  • enum
  • Struct 對一些基礎型別的封裝,對應C#中Class欄位
  • 還有一些集合的定義,包含 set<> 對應C#中的HashSet,是一種唯一元素的集合(Thrift框架自己定義了THashSet型別與之相對應);list<>對應C#中的List<>;map<K,V>對應C#的Dictionary<K,V>
  • service 這個是thrift的重點,它是一些方法集合,thrift會根據這個定義生成客戶端程式碼和服務端程式碼
  • exception 對應C#中的Exception型別
    thrift關於型別的定義以及示例程式碼請開啟這個網址:IDL描述

在IDL描述檔案中,Thrift除了對型別的定義外,我們還需要記住一下知識點:

  • namespace 在描述檔案的頭部定義。 以當前檔案為根目錄,生成多級目錄;在生成的程式碼上新增namespace名稱空間。程式碼如下:
namespace csharp WpfApp1.ceshi
  • include 在描述檔案的頭部定義。 用該命令包含其他thrift描述檔案,當編譯生成程式碼時也會編譯include指定的thrift檔案。程式碼如下:
include "pe1.thrift"

使用方法,pe1.thrift檔案定義如下:

struct pe1
{
 1: i32 id;
}

在其他檔案中,引入上述檔案,定義如下:

include "pe1.thrift"

service GuidGenService
{
   string getGuid(1:pe1.pe1 pe1);
}
  • typedef 型別定義命令,將thrift支援的型別定義一個別名。程式碼如下:
typedef i32 int
struct People
{
1: int ID;
2: string Name;
3: i16 Age;
4: list<i32> onelist;
5: set<string> oneSet;
6: map<i32,string> oneset;
}

當定義完描述檔案後,我們通過如下cmd命令生成程式碼檔案:

thrift-0.12.0.exe -r -gen csharp People.thrift

我們先要通過cd 將當前路徑跳轉到thrift-0.12.0.exe所在的路徑

示例

我定義了了一個描述檔案,如下:

namespace csharp WpfApp1.ceshi
include "pe1.thrift"

typedef i32 int

struct People
{
1: int ID;
2: string Name;
3: i16 Age;
4: list<i32> onelist;
5: set<string> oneSet;
6: map<i32,string> oneset;
}

service HelloService
{
 void SetPeople(1: People people1);
}

service GuidGenService
{
  string getGuid(1:pe1.pe1 pe1);
}

我們通過上述命令執行後,生成的程式碼結構如下圖:

我們開啟people.cs可以看到struct people生成了如下程式碼:

namespace WpfApp1.ceshi
{
  #if !SILVERLIGHT
  [Serializable]
  #endif
  public partial class People : TBase
  {
    private int _ID;
    private string _Name;
    private short _Age;
    private List<int> _onelist;
    private THashSet<string> _oneSet;
    private Dictionary<int, string> _oneset;
    .....

這裡需要注意一下people類的名稱空間,這和我們上文講的時一致的。
我們定義的service GuidGenService生成了如下程式碼:

該類是我們使用該框架的重點,它給我們生成了客戶端和伺服器端程式碼,從圖中我們可以看該檔案下生成了兩個介面ISync和Iface,前者是同步方法,後者生成的是非同步呼叫方法,接下來是一個供我們客戶端呼叫的類,它繼承了iface介面,而iface又繼承了ISync介面;再往下看是一個Processor,是服務端使用的類。

結尾

這篇檔案我們講了從0到1使用thrift框架的方法,也講了一些該框架的基本知識,接下來的檔案,我們將通過一個示例具體講解一下service指令程式碼生成的程式碼的具體含義和使用方法

相關文章