python thrift使用實例


 

前言

Apache Thrift 是 Facebook 實現的一種高效的、支持多種編程語言的遠程服務調用的框架。本文將從 Python開發人員角度簡單介紹 Apache Thrift 的架構、開發和使用。

Thrift簡介

Thrift network stack

Transport

Transport網絡讀寫(socket,http等)抽象,用於和其他thrift組件解耦。
Transport的接口包括:open, close, read, write, flush, isOpen, readAll。
Server端需要ServerTransport(對監聽socket的一種抽象),用於接收客戶端連接,接口包括:listen, accept, close。
python中Transport的實現包括:TSocket, THttpServer, TSSLSocket, TTwisted, TZlibTransport,都是對某種協議或框架的實現。還有兩個裝飾器,用於為已有的Transport添加功能,TBufferedTransport(增加緩沖)和TFramedTransport(添加幀)。
在創建server時,傳入的時Tranport的工廠,這些Factory包括:TTransportFactoryBase(沒有任何修飾,直接返回),TBufferedTransportFactory(返回帶緩沖的Transport)和TFramedTransportFactory(返回幀定位的Transport)。

Protocol

Protocol用於對數據格式抽象,在rpc調用時序列化請求和響應。
TProtocol的實現包括:TJSONProtocol,TSimpleJSONProtocol,TBinaryProtocol,TBinaryPotocolAccelerated,TCompactProtocol。

Processor

Processor對stream讀寫抽象,最終會調用用戶編寫的handler已響應對應的service。具體的Processor有compiler生成,用戶需要實現service的實現類。

Server

Server創建Transport,輸入、輸出的Protocol,以及響應service的handler,監聽到client的請求然后委托給processor處理。 TServer是基類,構造函數的參數包括: 1) processor, serverTransport 2) processor, serverTransport, transportFactory, protocolFactory 3) processor, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory TServer內部實際上需要3)所列的參數,1)和2)會導致對應的參數使用默認值。 TServer的子類包括:TSimpleServer, TThreadedServer, TThreadPoolServer, TForkingServer, THttpServer, TNonblockingServer, TProcessPoolServer TServer的serve方法用於開始服務,接收client的請求。

Code generated

constants.py: 包含聲明的所有常量
ttypes.py: 聲明的struct,實現了具體的序列化和反序列化
SERVICE_NAME.py: 對應service的描述文件,包含了:
Iface: service接口定義
Client: client的rpc調用樁

用法

Thrift的用法實際上很簡單,定義好IDL,然后實現service對應的handler(方法名、參數列表與接口定義一致接口),最后就是選擇各個組件。
需要選擇的包括:Transport(一般都是socket,只是十分需要選擇buffed和framed裝飾器factory),Protocol,Server。

示例

簡單記錄下在mac下使用python thrift的過程

1. 安裝 Thrift 的 python 庫有兩種方案(1. pip安裝 2. 源碼安裝)具體參見文末鏈接

    1)pip安裝: pip install thrift(最好在venv中使用)

2. 安裝 Thrift 的 IDL 編譯工具(windows/linux安裝見文末鏈接)

    1)mac下安裝: brew install thrift

    $ thrift -version,如果打印出來:Thrift version x.x.x 表明 complier 安裝成功

3. 建立項目目錄(thrift_demo)並開始編碼

    1)目錄結構(example目錄及其下的文件不用手動創建,是通過命令自動生成的,具體細節請往下看)

       

       <1> client目錄下的 client.py 實現了客戶端用於發送數據並打印接收到 server 端處理后的數據

       <2> server 目錄下的 server.py 實現了服務端用於接收客戶端發送的數據,並對數據進行大寫處理后返回給客戶端

       <3> thrift_file 用於存放 thrift 的 IDL 文件: *.thrift

   2) 定義 Thrift RPC 接口IDL文件 example.thrift:

namespace py example

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

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

進入 thrift_file 目錄執行:$ thrift -out .. --gen py example.thrift,就會在 thrift_file 的同級目錄下生成 python 的包:example

  3) 實現 server 端server.py:

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
cur_path =os.path.abspath(os.path.join(os.path.dirname('__file__'), os.path.pardir))
sys.path.append(cur_path)

from example import format_data
from example import ttypes
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

__HOST = 'localhost'
__PORT = 9000


class FormatDataHandler(object):
    def do_format(self, data):
        print(data.text, data.id)
        # can do something
        return ttypes.Data(data.text.upper(), data.id)


if __name__ == '__main__':
    handler = FormatDataHandler()

    processor = format_data.Processor(handler)
    transport = TSocket.TServerSocket(__HOST, __PORT)
    # 傳輸方式,使用buffer
    tfactory = TTransport.TBufferedTransportFactory()
    # 傳輸的數據類型:二進制
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()

    # 創建一個thrift 服務
    rpcServer = TServer.TSimpleServer(processor,transport, tfactory, pfactory)

    print('Starting the rpc server at', __HOST,':', __PORT)
    rpcServer.serve()
    print('done')

  4) 實現 client 端client.py:

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname('__file__'), os.path.pardir)))

from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from example.format_data import Client
from example.format_data import Data


__HOST = 'localhost'
__PORT = 9000


try:
    tsocket = TSocket.TSocket(__HOST, __PORT)
    transport = TTransport.TBufferedTransport(tsocket)
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
    client = Client(protocol)

    data = Data('hello,world!', 123)
    transport.open()
    print('client-requets')
    res = client.do_format(data)
    # print(client.do_format(data).text)
    print('server-answer', res)

    transport.close()
except Thrift.TException as ex:
    print(ex.message)

4. 執行驗證結果

    1) 先啟動 server(進入server目錄,執行python server.py),之后再另一個窗口執行 client(進入client目前,執行python client.py):

     client 側控制台打印的結果為:

     

    server側控制台打印的結果為:

    

    證明 Thrift 的 RPC 接口定義成功

 ================================部分詳細介紹========================================

傳輸協議 

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

  • 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 腳本可定義的數據類型包括以下幾種類型:

  • 基本類型:
    • bool:布爾值,true 或 false
    • byte:8 位有符號整數
    • i16:16 位有符號整數
    • i32:32 位有符號整數
    • i64:64 位有符號整數
    • double:64 位浮點數
    • string:未知編碼文本或二進制字符串
  • 結構體類型:
    • struct:定義公共的對象,類似於 C 語言中的結構體定義
  • 容器類型:
    • list:一系列 t1 類型的元素組成的有序表,元素可以重復
    • set:一系列 t1 類型的元素組成的無序表,元素唯一
    • map<t1,t2>:key/value 對(key 的類型是 t1 且 key 唯一,value 類型是 t2)
  • 異常類型:
    • exception 異常在語法和功能上類似於結構體,它在語義上不同於結構體—當定義一個 RPC 服務時,開發者可能需要聲明一個遠程方法拋出一個異常。
  • 服務類型:
    • service:對應服務的類

參考:

Python RPC 之 Thrift(含thrift及thrift IDL如何安裝)

Python Thrift示例

thrift Python Tutorial

Thrift network stack

Thrift Tutorial

Thrift 應用總結


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM