肝,Python3中RPC实践
什么是RPC?
百度百科給出的解釋是這樣的:“RPC(Remote Procedure Call)——遠程過程調用,它是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的協議”。
REST Vs RPC
微服務中服務之間的通信,大部分有兩種:即為RESTful和RPC。但是rest和rpc并不屬于同一類對比的種類。rest是定義了一種設計風格和開發方式,rpc是定義了一種協議。
所屬類別不同
REST,是Representational State Transfer 的簡寫,中文描述表述性狀態傳遞(是指某個瞬間狀態的資源數據的快照,包括資源數據的內容、表述格式(XML、JSON)等信息。)
REST 是一種軟件架構風格。這種風格的典型應用,就是HTTP。其因為簡單、擴展性強的特點而廣受開發者的青睞。
而RPC 呢,是 Remote Procedure Call Protocol 的簡寫,中文描述是遠程過程調用,它可以實現客戶端像調用本地服務(方法)一樣調用服務器的服務(方法)。
RPC 是一種基于 TCP 的通信協議,按理說它和REST不是一個層面上的東西,不應該放在一起討論,但是誰讓REST這么流行呢,它是目前最流行的一套互聯網應用程序的API設計標準,某種意義下,我們說 REST 可以其實就是指代 HTTP 協議。
使用方式不同
從使用上來看,HTTP 接口只關注服務提供方,對于客戶端怎么調用并不關心。接口只要保證有客戶端調用時,返回對應的數據就行了。而RPC則要求客戶端接口保持和服務端的一致。
?REST 是服務端把方法寫好,客戶端并不知道具體方法。客戶端只想獲取資源,所以發起HTTP請求,而服務端接收到請求后根據URI經過一系列的路由才定位到方法上面去?PRC是服務端提供好方法給客戶端調用,客戶端需要知道服務端的具體類,具體方法,然后像調用本地方法一樣直接調用它。
面向對象不同
從設計上來看,RPC,所謂的遠程過程調用 ,是面向方法的 ,REST:所謂的 Representational state transfer ,是面向資源的
序列化協議不同
接口調用通常包含兩個部分,序列化和通信協議。
通信協議,上面已經提及了,REST 是 基于 HTTP 協議,而 RPC 可以基于 TCP/UDP,也可以基于 HTTP 協議進行傳輸的。
常見的序列化協議,有:json、xml、hession、protobuf、thrift、text、bytes等,REST 通常使用的是 JSON或者XML,而 RPC 使用的是 JSON-RPC,或者 XML-RPC。
應用
?REST 接口更加規范,通用適配性要求高,建議對外的接口都統一成 REST(也有例外,比如我接觸過 zabbix,其 API 就是基于 JSON-RPC 2.0協議的)。而組件內部的各個模塊,可以選擇 RPC,一個是不用耗費太多精力去開發和維護多套的HTTP接口,一個RPC的調用性能更?從性能角度看,由于HTTP本身提供了豐富的狀態功能與擴展功能,但也正由于HTTP提供的功能過多,導致在網絡傳輸時,需要攜帶的信息更多,從性能角度上講,較為低效。而RPC服務網絡傳輸上僅傳輸與業務內容相關的數據,傳輸數據更小,性能更高。
python實現
Python3自帶xmlrpc,第三方有提供jsonrpc和zerorpc。
xmlrpc
?server(單線程)
from xmlrpc.server import SimpleXMLRPCServer from xmlrpc.server import SimpleXMLRPCRequestHandlerclass RequestHandler(SimpleXMLRPCRequestHandler):rpc_paths = ('/RPC2', '/RPC3')class Calculate:def add(self, x, y):return x + ydef multiply(self, x, y):return x * ydef subtract(self, x, y):return abs(x - y)def divide(self, x, y):return x / ywith SimpleXMLRPCServer(('localhost', 8000),requestHandler=RequestHandler) as server:server.register_introspection_functions()server.register_function(pow)@server.register_function(name='add1')def adder_function(x, y):return x + y + 1@server.register_functiondef mul(x, y):return x * yserver.register_instance(Calculate())server.serve_forever()?client
import xmlrpc.clientserver = xmlrpc.client.ServerProxy("http://localhost:8000")print(server.add(1, 2)) print(server.add1(1, 2)) print(server.pow(1, 2)) print(server.multiply(1, 2)) print(server.system.listMethods())?server(多線程)
from socketserver import ThreadingMixInclass ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):pass # 多線程class MultRequestHandler(SimpleXMLRPCRequestHandler):rpc_paths = ('/MRPC',)# 多線程 with ThreadXMLRPCServer(('localhost', 8001), requestHandler=MultRequestHandler, allow_none=True) as mserver:mserver.register_introspection_functions()mserver.register_multicall_functions()@mserver.register_function(name='add')def madd(a, b):return a + bmserver.serve_forever()?輸出結果
## server端 127.0.0.1?-?-?[02/Feb/2021?10:21:14]?"POST?/RPC2?HTTP/1.1" 200?- 127.0.0.1?-?-?[02/Feb/2021?10:21:14]?"POST?/RPC2?HTTP/1.1" 200?- 127.0.0.1?-?-?[02/Feb/2021?10:21:14]?"POST?/RPC2?HTTP/1.1" 200?- 127.0.0.1?-?-?[02/Feb/2021?10:21:14]?"POST?/RPC2?HTTP/1.1" 200?- 127.0.0.1?-?-?[02/Feb/2021?10:21:14]?"POST?/RPC2?HTTP/1.1" 200?- ## client端 3 4 1 2 ['add',?'add1',?'divide',?'mul',?'multiply',?'pow', 'subtract',?'system.listMethods',?'system.methodHelp',?'system.methodSignature']jsonrpc
?安裝
# python3 pip3 install jsonrpclib-pelix?server(單線程)
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer# 單線程 server = SimpleJSONRPCServer(('localhost', 8080)) server.register_function(lambda x, y: x + y, 'add') server.serve_forever()?client
import jsonrpclibserver = jsonrpclib.Server("http://localhost:8080") print(server.add(1, 2))?server(多線程)
# 多線程 from jsonrpclib.threadpool import ThreadPool# Setup the thread pool: between 0 and 10 threads pool = ThreadPool(max_threads=10, min_threads=0)# Don't forget to start it pool.start()# Setup the server server = SimpleJSONRPCServer(('localhost', 8080)) server.set_notification_pool(pool)# Register methods server.register_function(pow) server.register_function(lambda x, y: x + y, 'add') server.register_function(lambda x: x, 'ping')try:server.serve_forever() finally:# Stop the thread pool (let threads finish their current task)pool.stop()server.set_notification_pool(None)?輸出
# server 127.0.0.1 - - [02/Feb/2021 10:54:04] "POST / HTTP/1.1" 200 - # client 3Process finished with exit code 0zerorpc
xmlrpc和jsonrpc都是是用http+tcp的兩種協議相結合的方式,zerorpc是完全給予TCP協議實現,相對http性能更高一些。
?安裝
pip3 install zerorpc?server
import zerorpcclass caculate(object):def hello(self, name):return 'hello, {}'.format(name)def add(self, x, y):return x + ydef multiply(self, x, y):return x * ydef subtract(self, x, y):return abs(x - y)def divide(self, x, y):return x / ys = zerorpc.Server(caculate())s.bind("tcp://0.0.0.0:4242") s.run()?client
import zerorpcc = zerorpc.Client() c.connect("tcp://127.0.0.1:4242") print(c.add(1, 2))性能測試
處于好奇,測試一下zerorpc和jsonrpc(單線程)情況下,統計client各循環10000次共使用的時間。
?jsonrpc
All time is %d 27.96554207801819?zerorpc
All time is %d 10.987850904464722zerorpc比jsonrpc性能還是很可觀的。
參考
從0到1:全面理解RPC遠程調用[1]
References
[1]?從0到1:全面理解RPC遠程調用:?https://www.cnblogs.com/wongbingming/p/11086773.html
各位伙伴們好,詹帥本帥搭建了一個個人博客和小程序,匯集各種干貨和資源,也方便大家閱讀,感興趣的小伙伴請移步小程序體驗一下哦!(歡迎提建議)推薦閱讀牛逼!Python常用數據類型的基本操作(長文系列第①篇) 牛逼!Python的判斷、循環和各種表達式(長文系列第②篇)牛逼!Python函數和文件操作(長文系列第③篇)牛逼!Python錯誤、異常和模塊(長文系列第④篇)總結
以上是生活随笔為你收集整理的肝,Python3中RPC实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国内Python最有钱途的方向,开发第二
- 下一篇: PyWebIO,让 Pandas 原地起