<微服務架構>—Thrift篇

簡介

Thrift由Facebook研發,主要用於各個服務之間的RPC通信(與上篇博客:gRPC同類),支持跨語言,常用的語言比如C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml都支持。Thrift是一個典型的 CS(客戶端/服務端) 結構,在服務器端實現代碼,提供接口;客戶端可以直接調用接口,客戶端和服務端可以使用不同的語言開發。既然客戶端和服務端能使用不同的語言開發,那麼一定就要有一種中間語言來關聯客戶端和服務端的語言,沒錯,這種語言就是IDL(Interface Description Language)

安裝

源碼安裝

# 下載安裝包
curl -# -O http://archive.apache.org/dist/thrift/0.9.2/thrift-0.9.2.tar.gz
# 下載完成後開始解壓
tar zxvf thrift-0.9.2.tar.gz
# 進入文件夾
cd thrift-0.9.2
# 初始化配置
./configure
# 開始構建
make
# 一定要用sudo,本機編譯
sudo make install
# 查看thrift是否生效
thrift --version
# 顯示:Thrift version 0.9.2 

macOS安裝

brew install thrift

安裝python thrift庫

pip install thrift

使用流程

  1. 明確要交互的數據格式和具體的方法,定義出thrift接口描述文件,以thrift爲後綴(英文叫做IntefaceDescription File)

  2. 調用thrift工具,依據thrift接口文件,生成RPC代碼;

  3. 服務器端程序引用thrift生成的RPC代碼,並實現thrift中定義的邏輯,然後啓動監聽,等待客戶端發來請求。

  4. 客戶端同樣引入並調用RPC代碼來與服務器端通信

Thrift基本語法

類型

Thrift類型系統包括預定義的基本類型,用戶自定義結構體,容器類型,異常和服務定義。

基本類型(Basic types)
  • bool: 布爾類型,true或false,佔1字節
  • byte: 有符號char
  • i16: 16位有符號整數
  • i32: 32位有符號整數
  • i64: 64位有符號整數
  • double: 64位浮點數
  • binary: 字符數組
  • string: 字符串(比如二進制字符串或者其他編碼過的文本)
容器(Containers)
  • list: 一系列由T類型的數據組成的有序列表,元素可以重複。會被轉換成C++中的vector,Java中的ArrayList,腳本語言中的數組等;
  • set: 一系列由T類型的數據組成的無序集合,元素不可重複。會轉換成C++中的set,Java中的HashSet、Python中的Set等;
  • map: 一個字典結構,key爲K類型,value爲V類型,相當於Java中的HMap<K,V>。一個含有多個key:value鍵值對的結構。會被轉換成C++中的map,Java中的HashMap,PHP中的關聯數組,Python/Ruby中的dictionary等
結構體類型(Structs)

Thrift結構體類型在概念上類似於C語言中結構體類型,Thrift結構體將會被轉換成面嚮對象語言中的類。
```c++
struct People {
1: required string name;
2: required i32 age = 20;
3: optional string sex;
}

可以看到,結構體中每一個域都有一個正整數標識符,這個標識符並不要求連續,但一旦定義,不建議再進行修改
另外,每個域前都會有required或optional的限定,前者表示是必填域,後者則表示是可選域。域是可以有默認值的,比如上例中的“age"。
如果一個域設置爲optional且在構造結構體時沒有給這個域賦值,那麼在使用這個結構體時,就會忽略掉這個optional的域

#### 異常(Exceptions)
異常在語法和功能上類似於結構體,一個差別是異常使用關鍵字exception而不是struct來聲明。但他們在語義上有明顯不同之處:當定義一個RPC服務時,我們可以聲明一個遠程方法能夠拋出一個異常。
```c++
exception RequestException {
    1: i32 code;
    2: string reason;
}
服務(Services)

服務的定義,與面向對象技術中定義一個接口很類似,而這些接口其實就是純虛函數。thrift編譯工具會根據服務的定義來產生相應的方法和函數。
每個服務,都包括了若干個函數,每個函數包括了若干參數和一個返回值(返回值可以是void.
(小技巧:返回值爲void的函數,你可以在函數名前加上oneway標識符,將此函數以異步模式執行,這樣在調用此函數後,函數會立即返回。)

對於返回void的函數,thrift仍然會確保函數返回,這樣就表示這個函數已被正確執行,且服務器端已有返回信息了。但是如果給void的函數前加上oneway,那麼此函數的返回只能表示數據已經進入傳輸層,並不能表示服務器端已經收到並返回了數據

```c++
service vulgar_detect{
bool is_vulgar(1:string title),
i32 calc(1: i32 num)
}


##### 傳輸協議 

在傳輸協議上總體劃分爲文本和二進制 ,爲節約帶寬,提高傳輸效率,一般情況下使用二進制類型的傳輸協議爲多數.

* TBinaryProtocol — 二進制編碼格式進行數據傳輸
* TCompactProtocol — 高效率的、密集的二進制編碼格式進行數據傳輸
* TJSONProtocol — 使用 JSON 的數據編碼協議進行數據傳輸
* TSimpleJSONProtocol — 只提供 JSON 只寫的協議,適用於通過腳本語言解析
* TDebugProtocol – 使用易懂的可讀的文本格式,以便於 debug
##### 數據傳輸

* TSocket — 使用阻塞式 I/O 進行傳輸,是最常見的模式
* TFramedTransport — 使用非阻塞方式,按塊的大小進行傳輸
* TNonblockingTransport — 使用非阻塞方式,用於構建異步客戶端
* TMemoryTransport – 將內存用於 I/O
* TZlibTransport – 使用 zlib 進行壓縮, 與其他傳輸方式聯合使用
* TFileTransport – 以文件形式進行傳輸
##### 服務端類型

* TSimpleServer — 單線程服務器端使用標準的阻塞式 I/O
* TThreadPoolServer —— 多線程服務器端使用標準的阻塞式 I/O
* TNonblockingServer —— 多線程服務器端使用非阻塞式 I/O

#### thrift編譯工具
在我們編寫好thrift接口描述文件之後,thrift編譯工具就要派上用場了,它的作用就是根據thrift接口描述文件來生成相應開發語言的RPC代碼.
在終端下輸入:
```shell
thrift --gen ${開發語言} ${thrift接口描述文件}

關於thrift的更多命令可以輸入:

thrift --help

實戰演練

  1. 定義接口文件example.thrift

```c++
namespace py example

struct Data {
1: string text
2: i32 id
}

service format_data {
Data do_format(1:Data data),
}


2. 用thrift命令編譯example.thrift文件生成python代碼
```shell
thrift -out . --gen py example.thrift
# 參數說明:
    -out .:表示生成的代碼在當前目錄,並且命名不帶gen-前綴,如果用-o參數是帶有gen-前綴的

這一步生成的代碼結構如下圖:
<微服務架構>—Thrift篇

  1. 參考服務端客戶端源代碼Github,或者直接git clone

  2. 先啓動服務端python server.py,再運行客戶端python client.py,輸入如下:
>>>client-requets
>>>server-answer Data(text='HELLO,WORLD!', id=123)
致辭,完結,歡迎大夥到github交流學習
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章