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

python實(shí)現(xiàn)一個(gè)簡(jiǎn)單RPC框架的示例

 更新時(shí)間:2020年10月28日 16:01:58   作者:FXL  
本文將會(huì)使用Python實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的RPC框架,不具有實(shí)用意義,但可以讓你清醒地理解RPC框架的幾個(gè)組成部分,只是比看Python自帶的xmlrpc清晰。

本文需要一點(diǎn)Python socket基礎(chǔ)。

回顧RPC

  • 客戶端(Client):服務(wù)調(diào)用方。
  • 客戶端存根(Client Stub):存放服務(wù)端地址信息,將客戶端的請(qǐng)求參數(shù)數(shù)據(jù)信息打包成網(wǎng)絡(luò)消息,再通過(guò)網(wǎng)絡(luò)傳輸發(fā)送給服務(wù)端。
  • 服務(wù)端存根(Server Stub):接收客戶端發(fā)送過(guò)來(lái)的請(qǐng)求消息并進(jìn)行解包,然后再調(diào)用本地服務(wù)進(jìn)行處理。
  • 服務(wù)端(Server):服務(wù)的真正提供者。
  • Network Service:底層傳輸,可以是 TCP 或 HTTP。

實(shí)現(xiàn)jsonrpc

在實(shí)現(xiàn)前,簡(jiǎn)單理一下整體思路。

1、Network Service 直接使用Python Socket相關(guān)的API實(shí)現(xiàn) 2.傳輸數(shù)據(jù)使用JSON,在Socket層會(huì)被壓成二進(jìn)制,我們無(wú)需關(guān)心。

模仿xmlrpc,Client與Server都采用Minix多繼承機(jī)制來(lái)實(shí)現(xiàn),每個(gè)類(lèi)負(fù)責(zé)自身的事情,最終暴露出現(xiàn)的只有一個(gè)類(lèi)中有限的方法。

先從Client端開(kāi)始實(shí)現(xiàn)。

# client.py

 

import rpcclient

 

c = rpcclient.RPCClient()

c.connect('127.0.0.1', 5000)

res = c.add(1, 2, c=3)

print(f'res: [{res}]')

實(shí)例化rpcclient.RPCClient類(lèi),然后調(diào)用connect方法鏈接Server端,隨后直接調(diào)用Server端的add方法,該方法的效果就是將傳入的數(shù)據(jù)進(jìn)行累加并將累加的結(jié)果返回,最后將add方法返回的結(jié)果打印出了。

RPCClient類(lèi)繼承于TCPClient類(lèi)與RPCStub類(lèi)。

# rpclient.py

class RPCClient(TCPClient, RPCStub):

    pass

其中TCPClient負(fù)責(zé)通過(guò)Socket實(shí)現(xiàn)TCP鏈接并將數(shù)據(jù)請(qǐng)求過(guò)去,而RPCStub類(lèi)主要將Client端調(diào)用Server端方法的相關(guān)信息打包,然后調(diào)用TCPClient類(lèi)中的方法發(fā)送則可,兩個(gè)類(lèi)同樣實(shí)現(xiàn)在rpclient.py文件中,代碼如下。

class TCPClient(object):

    def __init__(self):

        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

 

    def connect(self, host, port):

        '''鏈接Server端'''

        self.sock.connect((host, port))

 

    def send(self, data):

        '''將數(shù)據(jù)發(fā)送到Server端'''

        self.sock.send(data)

 

    def recv(self, length):

        '''接受Server端回傳的數(shù)據(jù)'''

        return self.sock.recv(length)

         

 

class RPCStub(object):

    def __getattr__(self, function):

        def _func(*args, **kwargs):

            d = {'method_name': function, 'method_args': args, 'method_kwargs': kwargs}

            self.send(json.dumps(d).encode('utf-8')) # 發(fā)送數(shù)據(jù)

            data = self.recv(1024) # 接收方法執(zhí)行后返回的結(jié)果

            return data

 

        setattr(self, function, _func)

        return _func

TCPClient類(lèi)就是常規(guī)的Socket API的操作,無(wú)需多言,主要看看RPCStub類(lèi)。

當(dāng)我們?cè)贑lient端調(diào)用res = c.add(1, 2, c=3)時(shí),會(huì)執(zhí)行RPCStub中的__getattr__方法,該方法會(huì)將Client端調(diào)用的方法、參數(shù)等信息通過(guò)TCPServer類(lèi)的send方法發(fā)送,發(fā)送數(shù)據(jù)進(jìn)行了JSON格式化,方便Server端解碼,隨后便調(diào)用recv方法等待Server端相應(yīng)的數(shù)據(jù)返回。

因?yàn)镽PCClient類(lèi)本身沒(méi)有add方法,為了讓用戶做到Client端直接調(diào)用Server端方法的形式,先利用__getattr__構(gòu)建了_func方法,并將其通過(guò)setattr方法設(shè)置到RPCClient類(lèi)中,此時(shí)該類(lèi)就有Server端方法對(duì)應(yīng)的映射了。

調(diào)用add方法,就調(diào)用了對(duì)應(yīng)的_func方法,將數(shù)據(jù)發(fā)送至Server端。

Client端就這樣搞定了,接著來(lái)實(shí)現(xiàn)Server端,不用緊張,非常簡(jiǎn)單。

Server端的使用方式如下。

# server.py

 

import rpcserver

 

def add(a, b, c=10):

    sum = a + b + c

    return sum

 

s = rpcserver.RPCServer()

s.register_function(add) # 注冊(cè)方法

s.loop(5000) # 傳入要監(jiān)聽(tīng)的端口

實(shí)例化rpcserver.RPCServer類(lèi),然后通過(guò)register_function方法將想被Client端調(diào)用的方法傳入,隨后調(diào)用loop方法,將要監(jiān)聽(tīng)的端口傳入,RPCServer類(lèi)的實(shí)現(xiàn)如下。

# rpcserver.py

 

class RPCServer(TCPServer, JSONRPC, RPCStub):

    def __init__(self):

        TCPServer.__init__(self)

        JSONRPC.__init__(self)

        RPCStub.__init__(self)

 

    def loop(self, port):

        # 循環(huán)監(jiān)聽(tīng) 5000 端口

        self.bind_listen(port)

        print('Server listen 5000 ...')

        while True:

            self.accept_receive_close()

 

    def on_msg(self, data):

        return self.call_method(data)

RPCServer繼承自TCPServer、JSONRPC、RPCStub,這些類(lèi)同樣實(shí)現(xiàn)在rpcserver.py文件中并且給出了詳細(xì)的注釋?zhuān)跃驮敿?xì)解釋了。

class TCPServer(object):

    def __init__(self):

        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

 

    def bind_listen(self, port):

        self.sock.bind(('0.0.0.0', port))

        self.sock.listen(5)

 

    def accept_receive_close(self):

        '''獲取Client端信息'''

        (client_socket, address) = self.sock.accept()

        msg = client_socket.recv(1024)

        data = self.on_msg(msg)

        client_socket.sendall(data) # 回傳

        client_socket.close()

 

 

class JSONRPC(object):

    def __init__(self):

        self.data = None

 

    def from_data(self, data):

        '''解析數(shù)據(jù)'''

        self.data = json.loads(data.decode('utf-8'))

 

    def call_method(self, data):

        '''解析數(shù)據(jù),調(diào)用對(duì)應(yīng)的方法變將該方法執(zhí)行結(jié)果返回'''

        self.from_data(data)

        method_name = self.data['method_name']

        method_args = self.data['method_args']

        method_kwargs = self.data['method_kwargs']

        res = self.funs[method_name](*method_args, **method_kwargs)

        data = {"res": res}

        return json.dumps(data).encode('utf-8')

 

 

class RPCStub(object):

    def __init__(self):

        self.funs = {}

 

    def register_function(self, function, name=None):

        '''Server端方法注冊(cè),Client端只可調(diào)用被注冊(cè)的方法'''

        if name is None:

            name = function.__name__

        self.funs[name] = function

至此,Client端和Server端都寫(xiě)好了。

測(cè)試:

以上就是python實(shí)現(xiàn)一個(gè)簡(jiǎn)單RPC框架的示例的詳細(xì)內(nèi)容,更多關(guān)于python 實(shí)現(xiàn)RPC框架的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • python動(dòng)畫(huà)manim中的顏色ManimColor的使用方法詳解

    python動(dòng)畫(huà)manim中的顏色ManimColor的使用方法詳解

    這篇文章主要介紹了python動(dòng)畫(huà)manim中的顏色ManimColor的使用方法,本文通過(guò)實(shí)例圖文展示給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-08-08
  • 手把手教你快速安裝gpu版本的pytorch(詳細(xì)圖文教程)

    手把手教你快速安裝gpu版本的pytorch(詳細(xì)圖文教程)

    在Windows?10上安裝PyTorch時(shí),通常默認(rèn)安裝的是CPU版本,且下載速度較慢,本文提供了一個(gè)詳細(xì)的安裝指南,包括如何檢查CUDA版本、選擇合適的PyTorch、torchvision和torchaudio版本,并通過(guò)pip而非conda進(jìn)行安裝,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-09-09
  • python之如何使用openpyxl設(shè)置單元格樣式

    python之如何使用openpyxl設(shè)置單元格樣式

    這篇文章主要介紹了python之如何使用openpyxl設(shè)置單元格樣式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Python在字典中查找元素的3種方式

    Python在字典中查找元素的3種方式

    這篇文章主要介紹了Python在字典中查找元素的3種方式,字典是另一種可變?nèi)萜髂P?且可存儲(chǔ)任意類(lèi)型對(duì)象,需要的朋友可以參考下
    2023-04-04
  • python自動(dòng)定時(shí)任務(wù)schedule庫(kù)的使用方法

    python自動(dòng)定時(shí)任務(wù)schedule庫(kù)的使用方法

    當(dāng)你需要在 Python 中定期執(zhí)行任務(wù)時(shí),schedule 庫(kù)是一個(gè)非常實(shí)用的工具,它可以幫助你自動(dòng)化定時(shí)任務(wù),本文給大家介紹了python自動(dòng)定時(shí)任務(wù)schedule庫(kù)的使用方法,需要的朋友可以參考下
    2024-02-02
  • Python爬蟲(chóng)庫(kù)BeautifulSoup的介紹與簡(jiǎn)單使用實(shí)例

    Python爬蟲(chóng)庫(kù)BeautifulSoup的介紹與簡(jiǎn)單使用實(shí)例

    BeautifulSoup是一個(gè)可以從HTML或XML文件中提取數(shù)據(jù)的Python庫(kù),本文為大家介紹下Python爬蟲(chóng)庫(kù)BeautifulSoup的介紹與簡(jiǎn)單使用實(shí)例其中包括了,BeautifulSoup解析HTML,BeautifulSoup獲取內(nèi)容,BeautifulSoup節(jié)點(diǎn)操作,BeautifulSoup獲取CSS屬性等實(shí)例
    2020-01-01
  • 利用python獲取Ping結(jié)果示例代碼

    利用python獲取Ping結(jié)果示例代碼

    這篇文章主要給大家介紹了關(guān)于利用python獲取Ping結(jié)果的相關(guān)資料,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。
    2017-07-07
  • Python常用內(nèi)建模塊hashlib、hmac詳解

    Python常用內(nèi)建模塊hashlib、hmac詳解

    這篇文章主要介紹了Python常用內(nèi)建模塊hashlib、hmac詳解,摘要算法又稱哈希算法、散列算法,它通過(guò)一個(gè)函數(shù),把任意長(zhǎng)度的數(shù)據(jù)轉(zhuǎn)換為一個(gè)長(zhǎng)度固定的數(shù)據(jù)串,需要的朋友可以參考下
    2023-08-08
  • Mac安裝python3的方法步驟

    Mac安裝python3的方法步驟

    這篇文章主要介紹了Mac安裝python3的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Python空間數(shù)據(jù)處理之GDAL讀寫(xiě)遙感圖像

    Python空間數(shù)據(jù)處理之GDAL讀寫(xiě)遙感圖像

    這篇文章主要介紹了Python空間數(shù)據(jù)處理之GDAL讀寫(xiě)遙感圖像,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08

最新評(píng)論