欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python如何通過protobuf實現(xiàn)rpc

 更新時間:2016年03月06日 07:47:18   作者:在于思考  
這篇文章主要為大家詳細(xì)介紹了python通過protobuf實現(xiàn)rpc的方法,感興趣的朋友可以參考一下

由于項目組現(xiàn)在用的rpc是基于google protobuf rpc協(xié)議實現(xiàn)的,所以花了點時間了解下protobuf rpc。rpc對于做分布式系統(tǒng)的人來說肯定不陌生,對于rpc不了解的童鞋可以自行g(shù)oogle,這里只是做個簡單的介紹。rpc的主要功能是讓分布式系統(tǒng)的實現(xiàn)更為簡單,為提供強大的遠(yuǎn)程調(diào)用而不損失本地調(diào)用語義的簡潔性。為了實現(xiàn)這個目標(biāo),rpc框架需要提供一種透明調(diào)用機(jī)制讓使用者不必顯示區(qū)分本地調(diào)用還是遠(yuǎn)程調(diào)用。rpc架構(gòu)涉及的組件如下:

客戶方像調(diào)用本地方法一樣去調(diào)用遠(yuǎn)程接口方法,RPC 框架提供接口的代理實現(xiàn),實際的調(diào)用將委托給代理RpcProxy 。代理封裝調(diào)用信息并將調(diào)用轉(zhuǎn)交給RpcInvoker 去實際執(zhí)行。在客戶端的RpcInvoker 通過連接器RpcConnector 去維持與服務(wù)端的通道RpcChannel,并使用RpcProtocol 執(zhí)行協(xié)議編碼(encode)并將編碼后的請求消息通過通道發(fā)送給服務(wù)方。RPC 服務(wù)端接收器 RpcAcceptor 接收客戶端的調(diào)用請求,同樣使用RpcProtocol 執(zhí)行協(xié)議解碼(decode)。解碼后的調(diào)用信息傳遞給RpcProcessor 去控制處理調(diào)用過程,最后再委托調(diào)用給RpcInvoker 去實際執(zhí)行并返回調(diào)用結(jié)果。

protobuf rpc在上面組件中主要扮演RpcProtocol的角色,使得我們省去了協(xié)議的設(shè)計,并且protobuf協(xié)議在編碼和空間效率都是上非常高效的,這也是很多公司采用protobuf作為數(shù)據(jù)序列化和通信協(xié)議的原因。同時protobuf rpc定義了一個抽象的rpc框架,如下圖所示:

RpcServiceStub和RpcService類是protobuf編譯器根據(jù)proto定義生成的類,RpcService定義了服務(wù)端暴露給客戶端的函數(shù)接口,具體實現(xiàn)需要用戶自己繼承這個類來實現(xiàn)。RpcServiceStub定義了服務(wù)端暴露函數(shù)的描述,并將客戶端對RpcServiceStub中函數(shù)的調(diào)用統(tǒng)一轉(zhuǎn)換到調(diào)用RpcChannel中的CallMethod方法,CallMethod通過RpcServiceStub傳過來的函數(shù)描述符和函數(shù)參數(shù)對該次rpc調(diào)用進(jìn)行encode,最終通過RpcConnecor發(fā)送給服務(wù)方。對方以客戶端相反的過程最終調(diào)用RpcSerivice中定義的函數(shù)。事實上,protobuf rpc的框架只是RpcChannel中定義了空的CallMethod,所以具體怎樣進(jìn)行encode和調(diào)用RpcConnector都要自己實現(xiàn)。RpcConnector在protobuf中沒有定義,所以這個完成由用戶自己實現(xiàn),它的作用就是收發(fā)rpc消息包。在服務(wù)端,RpcChannel通過調(diào)用RpcService中的CallMethod來具體調(diào)用RpcService中暴露給客戶端的函數(shù)。

介紹了這么多,對于怎么樣用protobuf rpc來實現(xiàn)一個rpc肯定還是一頭霧水吧,下面就用protobuf rpc來實現(xiàn)一個簡單的python版rpc demo吧。

下面直接給出demo描述PRC的proto文件,至于proto文件的編寫規(guī)則可以參考protobuf官網(wǎng)。

common.proto文件:

package game;

message RequestMessage
{
  required string message = 1;
}

message ResponseMessage
{
  required string message = 1;
}

game_service.proto文件:

package game;

import "common.proto";
option py_generic_services = true;

service GameService
{
  rpc connect_server(RequestMessage) returns(RequestMessage);
}

common.proto文件描述了RPC中收發(fā)的消息;game_service.proto描述了服務(wù)器導(dǎo)出的connect_server函數(shù),該函數(shù)接受RequestMessage對象作為參數(shù),并返回RequestMessage對象。在使用PRC協(xié)議時,必須加上option py_generic_services  = true;可選項,要不然編譯器不會生成包含connect_server函數(shù)的GameService描述。

使用編譯器protoc編譯proto文件,具體命令為:
protoc.exe --python_out=. game_service.proto
編譯后生成的文件為game_service_pb2.py,該文件主要是實現(xiàn)了GameService和GameService_Stub類。GameService_Stub類用于客戶端調(diào)用者來調(diào)用GameService的服務(wù)。
前面已經(jīng)說了,在客戶端,RpcChannel只實現(xiàn)了一個空的CallMethod,所以需要繼承RpcChannel重新這個函數(shù)來encode消息和發(fā)送消息。在服務(wù)端RpcChannel需要調(diào)用CallMethod來調(diào)用Service中的函數(shù)。具體實現(xiàn)如下:

class MyRpcChannel(service.RpcChannel):
  def __init__(self, rpc_service, conn):
    super(MyRpcChannel, self).__init__()
    self.logger = LogManager.get_logger("MyRpcChannel")

  def CallMethod(self, method_descriptor, rpc_controller, request, response_class, done):
    """"protol buffer rpc 需要的函數(shù),用來發(fā)送rpc調(diào)用"""
    self.logger.info('CallMethod')
    cmd_index = method_descriptor.index
    assert(cmd_index < 65535)
    data = request.SerializeToString()
    total_len = len(data) + 2
    self.conn.send_data(''.join([pack('<I', total_len), pack('<H', cmd_index), data]))

  def from_request(self):
    """"從網(wǎng)絡(luò)解析出一個完整的請求之后調(diào)的函數(shù)"""
    index_data = self.rpc_request.data[0:2]    
    cmd_index = unpack('<H', index_data)[0]  
    rpc_service = self.rpc_service
    s_descriptor = rpc_service.GetDescriptor()
    method = s_descriptor.methods[cmd_index]  
    try:
      request = rpc_service.GetRequestClass(method)()
      serialized = self.rpc_request.data[2:]    
      request.ParseFromString(serialized)  
      rpc_service.CallMethod(method, self.controller, request, None)
    except:
      self.logger.error("Call rpc method failed!")
      self.logger.log_last_except()
    return True

最后就是繼承GameService,并實現(xiàn)connect_server函數(shù)了。

class GameService(game_service_pb2.GameService):
  def __init__(self):
    self.logger = LogManager.get_logger("GameService")

  def connect_server(self, rpc_controller, request, callback):
    self.logger.info('%s', request.message)

 至于用于網(wǎng)絡(luò)收發(fā)消息的RpcConnector,可以使用python的asyncore庫實現(xiàn),具體實現(xiàn)在這就不討論了。

從上面的實現(xiàn)來看,protobuf rpc的實現(xiàn)主要包括編寫proto文件并編譯生成對應(yīng)的service_pb2文件,繼承RpcChannel并實現(xiàn)CallMethod和調(diào)用Service的CallMethod,繼承Service來實現(xiàn)暴露給客戶端的函數(shù)。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • Python中的十大圖像處理工具(小結(jié))

    Python中的十大圖像處理工具(小結(jié))

    這篇文章主要介紹了Python中的十大圖像處理工具,本文主要介紹了一些簡單易懂最常用的Python圖像處理庫,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • 手把手教你python實現(xiàn)SVM算法

    手把手教你python實現(xiàn)SVM算法

    這篇文章主要為大家詳細(xì)介紹了手把手教你python實現(xiàn)SVM算法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • 理解python多線程(python多線程簡明教程)

    理解python多線程(python多線程簡明教程)

    這篇文章主要介紹了理解python多線程,一個快速理解python多線程的簡明教程,需要的朋友可以參考下
    2014-06-06
  • 詳解如何在ChatGPT內(nèi)構(gòu)建一個Python解釋器

    詳解如何在ChatGPT內(nèi)構(gòu)建一個Python解釋器

    這篇文章主要為大家詳細(xì)介紹了如何在ChatGPT內(nèi)構(gòu)建一個Python解釋器,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,需要的可以參考一下
    2023-02-02
  • python嵌套try...except如何使用詳解

    python嵌套try...except如何使用詳解

    有時候我們寫程序的時候,會出現(xiàn)一些錯誤或異常,導(dǎo)致程序終止,使用try…except,這樣程序就不會因為異常而中斷,下面這篇文章主要給大家介紹了關(guān)于python嵌套try...except如何使用的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • 利用Python生成文件md5校驗值函數(shù)的方法

    利用Python生成文件md5校驗值函數(shù)的方法

    這篇文章主要給大家介紹了利用Python生成文件md5校驗值函數(shù)的方法,文中給出了詳細(xì)的示例代碼,對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價值,有需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01
  • Django用戶認(rèn)證系統(tǒng) User對象解析

    Django用戶認(rèn)證系統(tǒng) User對象解析

    這篇文章主要介紹了Django用戶認(rèn)證系統(tǒng) User對象解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-08-08
  • Python+PyQt5實現(xiàn)開發(fā)Memcached客戶端

    Python+PyQt5實現(xiàn)開發(fā)Memcached客戶端

    這篇文章主要介紹了如何使用Python和PyQt5來制作一個Memcached客戶端,以便我們可以輕松地與Memcached服務(wù)器進(jìn)行交互,感興趣的小伙伴可以了解一下
    2023-06-06
  • pytorch算子torch.arange在CPU?GPU?NPU中支持?jǐn)?shù)據(jù)類型格式

    pytorch算子torch.arange在CPU?GPU?NPU中支持?jǐn)?shù)據(jù)類型格式

    這篇文章主要為大家介紹了pytorch算子torch.arange在CPU?GPU?NPU支持?jǐn)?shù)據(jù)類型格式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • python實現(xiàn)人臉識別經(jīng)典算法(一) 特征臉法

    python實現(xiàn)人臉識別經(jīng)典算法(一) 特征臉法

    這篇文章主要為大家詳細(xì)介紹了python實現(xiàn)人臉識別經(jīng)典算法,特征臉法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03

最新評論