用python實現(xiàn)RPC框架的方法

這篇文章將為大家詳細講解有關(guān)用python實現(xiàn)RPC框架的方法,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

愛輝網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)公司,愛輝網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為愛輝1000多家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務(wù)好的愛輝做網(wǎng)站的公司定做!

使用Python實現(xiàn)一個最簡單的RPC框架,不具有實用意義,但可以讓你清醒地理解RPC框架的幾個組成部分,只是比看Python自帶的xmlrpc清晰。

(推薦教程:Python入門教程)

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

回顧RPC

用python實現(xiàn)RPC框架的方法

  • 客戶端(Client):服務(wù)調(diào)用方。

  • 客戶端存根(Client Stub):存放服務(wù)端地址信息,將客戶端的請求參數(shù)數(shù)據(jù)信息打包成網(wǎng)絡(luò)消息,再通過網(wǎng)絡(luò)傳輸發(fā)送給服務(wù)端。

  • 服務(wù)端存根(Server Stub):接收客戶端發(fā)送過來的請求消息并進行解包,然后再調(diào)用本地服務(wù)進行處理。

  • 服務(wù)端(Server):服務(wù)的真正提供者。

  • Network Service:底層傳輸,可以是 TCP 或 HTTP。

實現(xiàn)jsonrpc

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

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

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

先從Client端開始實現(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}]')

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

RPCClient類繼承于TCPClient類與RPCStub類。

# rpclient.py

class RPCClient(TCPClient, RPCStub):
    pass

其中TCPClient負責(zé)通過Socket實現(xiàn)TCP鏈接并將數(shù)據(jù)請求過去,而RPCStub類主要將Client端調(diào)用Server端方法的相關(guān)信息打包,然后調(diào)用TCPClient類中的方法發(fā)送則可,兩個類同樣實現(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類就是常規(guī)的Socket API的操作,無需多言,主要看看RPCStub類。

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

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

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

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

Server端的使用方式如下。

# server.py

import rpcserver

def add(a, b, c=10):
    sum = a + b + c
    return sum

s = rpcserver.RPCServer()
s.register_function(add) # 注冊方法
s.loop(5000) # 傳入要監(jiān)聽的端口

實例化rpcserver.RPCServer類,然后通過register_function方法將想被Client端調(diào)用的方法傳入,隨后調(diào)用loop方法,將要監(jiān)聽的端口傳入,RPCServer類的實現(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)聽 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,這些類同樣實現(xiàn)在rpcserver.py文件中并且給出了詳細的注釋,所以就詳細解釋了。

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)用對應(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端方法注冊,Client端只可調(diào)用被注冊的方法'''
        if name is None:
            name = function.__name__
        self.funs[name] = function

至此,Client端和Server端都寫好了。

測試:

用python實現(xiàn)RPC框架的方法

關(guān)于用python實現(xiàn)RPC框架的方法就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

網(wǎng)頁標題:用python實現(xiàn)RPC框架的方法
路徑分享:http://bm7419.com/article10/gosido.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、網(wǎng)站內(nèi)鏈、App設(shè)計、移動網(wǎng)站建設(shè)、云服務(wù)器

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

手機網(wǎng)站建設(shè)