<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
這是一個遠端過程呼叫(RPC)的實現demo,可以實現不同的python程序之間通訊和互相呼叫函數,簡單易用,易於擴充套件。更多功能也可進一步完善,本文介紹了該實現的主要思路。
計劃手擼一個rpc甚久了,在間歇性push自己下終於完成的差不多了。寫這個demo的原因,1)是為了學習與思考下這部分主體功能和實現思路,2)是調包時可以毫無心理負擔,併產生一種不過如此的優越感。
實現這部分內容主要依據的還是自己的想法,因此可能會有bug或者有更好的實現方式,僅供學習和參考,完整程式碼可參考Gitee連結。
實現的時候用的是python2.7,忘記換了,下次一定更新。
所謂RPC,是遠端過程呼叫(Remote Procedure Call)的簡寫,網上解釋很多,簡單來說,就是在當前程序呼叫其他程序的函數時,體驗就像是呼叫本地寫的函數一般。
本文實現的是在本地呼叫遠端的類class物件的介面,也就是原生的client不範例化類物件,呼叫的是server端的類物件介面。
為了達到讓呼叫層無須關心底層實現,擁有絲滑般的體驗,就需要以下幾個部分:
在下面時序圖的灰色部分,對於呼叫方來說是透明的,它的執行結果應該和執行原生的函數時一致的。
本文采用了基於TCP的sokcet連線來進行程序之間的通訊,更多實現細節可參考之前部落格。
在此需要注意:
本文采用了select模組來監聽網路事件,如果伺服器端未收到任何的網路訊息會一直阻塞在這兒。如果伺服器端除了提供rpc呼叫服務之外還需要執行其他邏輯,那麼應當採用非阻塞,輪詢socket的方式來判斷是否有新的網路事件。
# ServerBase.py def process(self): readable, writable, exceptional = select.select(self.inputs, self.outputs, self.conns.values()) for conn in readable: if conn is self.socket: self._handle_conn() else: self._handle_recv(conn) for conn in writable: pass for conn in exceptional: self._handle_leave(conn)
使用者端的網路事件本文通過建立新的執行緒來監聽的。並不會影響使用者端主執行緒的執行,因此可以盡情的阻塞。部分程式碼如下:
# AsynCallback.py class AsyncTaskManager(object): _asy_events = dict() def __init__(self, loop, *args): super(AsyncTaskManager, self).__init__() self._loop_fun = loop def __call__(self, *args, **kwargs): proc = threading.Thread(target=self._exec_loop, args=args, kwargs=kwargs) proc.start() def _exec_loop(self, *args, **kwargs): while True: net_resp = self._loop_fun(*args, **kwargs) for resp in net_resp: asy_event = self._asy_events.pop(resp.rid) asy_event.set()
# Client.py class Client(TaskHandle, ClientBase): @AsyncTaskManager def process(self): super(Client, self).process() _events = [] while self.has_events: event = self.get_next_event() data = event[1] _events.append(self.unpack_respond(data)) return _events
序列化方式,本文采用了庫pickle進行序列化與反序列化,使用它的原因是可以將自定義類物件也進行序列化,非常之高階。
對於需要返回值的函數呼叫,處理起來比較簡單,只需要將主執行緒阻塞等待,直至超時或者接收到了對應函數的返回值即可。本文采用了threading.Event來阻塞與喚醒呼叫的函數,同時採用了裝飾器來實現這功能。若日後有更好的方法,可以輕易進行替換。相關範例程式碼如下所示:
@AsyncTaskManager.respond def _handle_response(self, tid): """ 處理有返回值的情況 會阻塞執行緒直至收到返回值 """ task = self.pop_task(tid) if task.callback: task.callback() return self.pop_respond(tid) @staticmethod def respond(func): @wraps(func) def make_resp(handle, tid): """ 需要注意的是,和裝飾的函數引數含義需一致 """ event = threading.Event() AsyncTaskManager._asy_events[tid] = event event.wait(timeout=TIME_OUT) return func(handle, tid) # 這兒才是真正執行_handle_response的地方 return make_resp
在實際的應用過程中,應有這樣的情況,伺服器端與使用者端都是獨立的應用,通過rpc函數進行通訊和互動,而並不是某方為另外一方提供服務,那麼此時返回值並不必要,只需要將要做的事通知另一方即可。對於此種情況,可以採用非同步回撥的方式來告知呼叫方對應函數執行成功了。
在文中依舊採用執行緒來完成該功能,使用者端呼叫函數之後建立一個新執行緒並阻塞住,等待伺服器端將執行結果發回後再喚醒,如果有回撥函數就執行。範例程式碼如下:
@AsyncTaskManager.callback def _handle_call_back(self, tid): """ 處理有回撥函數的呼叫 callback會等tid事件呼叫成功之後 才會回撥,且不會有返回值 """ task = self.pop_task(tid) if task.callback: task.callback() @staticmethod def callback(func): @wraps(func) def make_thread(event, *args, **kwargs): event.wait(timeout=TIME_OUT) func(*args, **kwargs) def make_async(handle, tid): """ 注意點同上 """ event = threading.Event() AsyncTaskManager._asy_events[tid] = event _task = threading.Thread(target=lambda: make_thread(event, handle, tid)) return make_async
到此這篇關於基於python實現rpc遠端過程呼叫的文章就介紹到這了,更多相關python rpc遠端呼叫內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45