基于Apache Thrift的公路涵洞数据交互实现原理
基于Apache Thrift的公路涵洞數據交互實現原理
Apache Thrift簡介
Apache Thrift(以下簡稱為“Thrift”) 是 Facebook 實現的一種高效的、支持多種編程語言的遠程服務調用的框架。
目前流行的服務調用方式有很多種,例如基于 SOAP 消息格式的 Web Service,基于 JSON 消息格式的 RESTful 服務等。其中所用到的數據傳輸方式包括 XML,JSON 等,然而 XML 相對體積太大,傳輸效率低,JSON 體積較小,新穎,但還不夠完善。本文將介紹由 Facebook 開發的遠程服務調用框架 Apache Thrift,它采用接口描述語言定義并創建服務,支持可擴展的跨語言服務開發,所包含的代碼生成引擎可以在多種語言中,如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等創建高效的、無縫的服務,其傳輸數據采用二進制格式,相對 XML 和 JSON 體積更小,對于高并發、大數據量和多語言的環境更有優勢。
Thrift 架構
Thrift 包含一個完整的堆棧結構用于構建客戶端和服務器端。下圖描繪了 Thrift 的整體架構。
圖 1. 架構圖
?
?
?
如圖所示,圖中黃色部分是用戶實現的業務邏輯,褐色部分是根據 Thrift 定義的服務接口描述文件生成的客戶端和服務器端代碼框架,紅色部分是根據 Thrift 文件生成代碼實現數據的讀寫操作。紅色部分以下是 Thrift 的傳輸體系、協議以及底層 I/O 通信,使用 Thrift 可以很方便的定義一個服務并且選擇不同的傳輸協議和傳輸層而不用重新生成代碼。
Thrift 服務器包含用于綁定協議和傳輸層的基礎架構,它提供阻塞、非阻塞、單線程和多線程的模式運行在服務器上,可以配合服務器 / 容器一起運行。
服務端和客戶端具體的調用流程如下:
圖 2. Server 端啟動、服務時序圖
?
該圖所示是 HelloServiceServer 啟動的過程以及服務被客戶端調用時,服務器的響應過程。從圖中我們可以看到,程序調用了 TThreadPoolServer 的 serve 方法后,server 進入阻塞監聽狀態,其阻塞在 TServerSocket 的 accept 方法上。當接收到來自客戶端的消息后,服務器發起一個新線程處理這個消息請求,原線程再次進入阻塞狀態。在新線程中,服務器通過 TBinaryProtocol 協議讀取消息內容,調用 HelloServiceImpl 的 helloVoid 方法,并將結果寫入 helloVoid_result 中傳回客戶端。
圖 3. Client 端調用服務時序圖
?
該圖所示是 HelloServiceClient 調用服務的過程以及接收到服務器端的返回值后處理結果的過程。從圖中我們可以看到,程序調用了 Hello.Client 的 helloVoid 方法,在 helloVoid 方法中,通過 send_helloVoid 方法發送對服務的調用請求,通過 recv_helloVoid 方法接收服務處理請求后返回的結果。
Thrift環境準備
1下載Thrift
當前版本為Thrift-0.10.0。
2. 編譯或下載Thrift編譯器
windows下可以直接下載已經編譯好的編譯器Thrift-0.10.0.exe。
涵洞數據交互實例:
1.?定義Thrift文件
exception GenericError {
}
enum SlabCulvertType {
}
struct CommonResult{
}
struct SlabCulvert {
}
service EngineerService {
????CommonResult slabCulvert_add(1: Context context,2: SlabCulvertType slabCulvertType,3: SlabCulvert slabCulvert) throws (1:GenericError e)
????CommonResult slabCulvert_modify(1: Context context,2: SlabCulvertCondition slabCulvertCondition,3: SlabCulvertType slabCulvertType,4: SlabCulvert slabCulvert) throws (1:GenericError e)
????CommonResult slabCulvert_remove(1: Context context,2: SlabCulvertCondition slabCulvertCondition) throws (1:GenericError e)
????SlabCulvertResult slabCulvert_query(1: Context context,2: SlabCulvertCondition slabCulvertCondition) throws (1:GenericError e)
}
2.?使用Thrift編譯器編譯Thrift文件
thrift --gen <language> <Thrift filename>
3.?編寫服務端代碼
#!/usr/bin/env python # -*- coding:utf-8 -*-import glob import sys sys.path.append('gen-py') sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0])from tutorial import EngineerServicefrom thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from thrift.server import TServerclass EngineerServiceHandler:def __init__(self):self.log = {}def slabCulvert_add(self, context, slabCulvertType, slabCulvert):passdef slabCulvert_modify(self, context, slabCulvertCondition, slabCulvertType, slabCulvert):passdef slabCulvert_remove(self, context, slabCulvertCondition):passdef slabCulvert_query(self, context, slabCulvertCondition):passif __name__ == '__main__':handler = EngineerServiceHandler()processor = EngineerService.Processor(handler)transport = TSocket.TServerSocket(port=9090)tfactory = TTransport.TBufferedTransportFactory()pfactory = TBinaryProtocol.TBinaryProtocolFactory()server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)print('Starting the server...')server.serve()print('done.')4.?客戶端使用框架代碼調用遠程服務
#!/usr/bin/env python # -*- coding:utf-8 -*-import sys import glob sys.path.append('gen-py') sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0])from tutorial import EngineerService from tutorial.ttypes import InvalidOperation, slabCulvertTypefrom thrift import Thrift from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocoldef main():# Make sockettransport = TSocket.TSocket('localhost', 9090)# Buffering is critical. Raw sockets are very slowtransport = TTransport.TBufferedTransport(transport)# Wrap in a protocolprotocol = TBinaryProtocol.TBinaryProtocol(transport)# Create a client to use the protocol encoderclient = EngineerService.Client(protocol)# Connect! transport.open()try:context = ...slab_culvert_type = ...slab_culvert = slabCulvert(...)res = client.slabCulvert_add(context, slab_culvert_type, slab_culvert)print(res)except InvalidOperation as e:print('InvalidOperation: %r' % e)# Close! transport.close()if __name__ == '__main__':try:main()except Thrift.TException as tx:print('%s' % tx.message)參考資料:
轉載于:https://www.cnblogs.com/yaoyu126/p/6724718.html
總結
以上是生活随笔為你收集整理的基于Apache Thrift的公路涵洞数据交互实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。