版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第Python用內(nèi)置模塊來構(gòu)建REST服務(wù)與RPC服務(wù)實戰(zhàn)print(name,value)
測試HTTP客戶端,考慮使用httpbin服務(wù)()。這個站點會接收發(fā)出的請求,然后以JSON的形式將相應(yīng)信息回傳回來。
importrequests
r=requests.get('/getname=Daven=37',
...headers={'User-agent':'goaway/1.0'})
resp=r.json()
resp['headers']
{'Accept':'*/*','Accept-Encoding':'gzip,deflate','Host':'','User-Agent':'goaway/1.0','X-Amzn-Trace-Id':'Root=1-62708c06-7c7d8cc4441479c65faea5b4'}
通過XML-RPC實現(xiàn)簡單的遠(yuǎn)程調(diào)用
RPC,通俗的講,想找到一個方式去運行在遠(yuǎn)程機(jī)器上面的Python程序中的函數(shù)或方法。
實現(xiàn)一個遠(yuǎn)程方法調(diào)用的最簡單方式是使用XML-RPC。下面實現(xiàn)了鍵值存儲功能的簡單RPC服務(wù)器:
"""
@File:app.py
@Author:LiRuilong
@Version:1.0
@Desc:None
#hereputtheimportlib
fromxmlrpc.serverimportSimpleXMLRPCServer
classKeyValueServer:
_rpc_methods_=['get','set','delete','exists','keys']
def__init__(self,address):
self._data={}
self._serv=SimpleXMLRPCServer(address,allow_none=True)
#注冊方法
fornameinself._rpc_methods_:
self._serv.register_function(getattr(self,name))
defget(self,name):
returnself._data[name]
defset(self,name,value):
self._data[name]=value
defdelete(self,name):
delself._data[name]
defexists(self,name):
returnnameinself._data
defkeys(self):
returnlist(self._data)
defserve_forever(self):
self._serv.serve_forever()
#Example
if__name__=='__main__':
kvserv=KeyValueServer(('',15001))
kvserv.serve_forever()
RPC客戶端測試
PSE:\dockerpython
Python3.9.0(tags/v3.9.0:9cf6752,Oct52025,15:23:07)[MSCv.192732bit(Intel)]onwin32
Type"help","copyright","credits"or"license"formoreinformation.
fromxmlrpc.clientimportServerProxy
s=ServerProxy('http://localhost:15001',allow_none=True)
s.set('foo','bar')
s.set('spam',[1,2,3])
s.keys()
['foo','spam']
s.get('foo')
'bar'
s.get('spam')
[1,2,3]
s.delete('spam')
s.exists('spam')
False
XML-RPC可以讓很容易的構(gòu)造一個簡單的遠(yuǎn)程調(diào)用服務(wù)。所需要做的僅僅是創(chuàng)建一個服務(wù)器實例,通過它的方法register_function()來注冊函數(shù),然后使用方法serve_forever()啟動它。在上面將這些步驟放在一起寫到一個類中
這并不是必須的。還可以像下面這樣創(chuàng)建一個服務(wù)器:
fromxmlrpc.serverimportSimpleXMLRPCServer
fromxmlrpc.serverimportSimpleXMLRPCServer
defadd(x,y):
returnx+y
serv=SimpleXMLRPCServer(('',15000))
serv.register_function(add)
serv.serve_forever()
XML-RPC暴露出來的函數(shù)只能適用于部分?jǐn)?shù)據(jù)類型,比如字符串、整形、列表和字典,不應(yīng)該將XML-RPC服務(wù)以公共API的方式暴露出來。
XML-RPC的一個缺點是它的性能。SimpleXMLRPCServer的實現(xiàn)是單線程的,所以它不適合于大型程序
由于XML-RPC將所有數(shù)據(jù)都序列化為XML格式,所以它會比其他的方式運行的慢一些。但是它也有優(yōu)點,這種方式的編碼可以被絕大部分其他編程語言支持。通過使用這種方式,其他語言的客戶端程序都能訪問的服務(wù)。
通過multiprocessing實現(xiàn)RPC調(diào)用
在一個消息傳輸層如sockets、multiprocessing.connections或zeroMQ的基礎(chǔ)之上實現(xiàn)一個簡單的遠(yuǎn)程過程調(diào)用(RPC)
將函數(shù)請求、參數(shù)和返回值使用pickle編碼后,在不同的解釋器直接傳送pickle字節(jié)字符串,可以很容易的實現(xiàn)RPC。下面是一個簡單的PRC處理器,可以被整合到一個服務(wù)器中去:
RPC服務(wù)端
"""
@File:rpcserver.py
@Author:LiRuilong
@Version:1.0
@Desc:遠(yuǎn)程調(diào)用服務(wù)
#hereputtheimportlib
importpickle
frommultiprocessing.connectionimportListener
fromthreadingimportThread
@Time:2025/07/0820:28:02
@Author:LiRuilong
@Version:1.0
@Desc:None
Args:
遠(yuǎn)程調(diào)用處理器
Returns:
void
classRPCHandler:
def__init__(self):
self._functions={}
@Time:2025/07/0820:16:47
@Author:LiRuilong
@Version:1.0
@Desc:函數(shù)注冊
Args:
func
Returns:
void
defregister_function(self,func):
self._functions[func.__name__]=func
@Time:2025/07/0820:17:51
@Author:LiRuilong
@Version:1.0
@Desc:調(diào)用函數(shù)
Args:
connection
Returns:
void
defhandle_connection(self,connection):
try:
whileTrue:
func_name,args,kwargs=pickle.loads(connection.recv())
try:
print("調(diào)用函數(shù):",(func_name,args,kwargs))
r=self._functions[func_name](*args,**kwargs)
print("返回結(jié)果:",r)
connection.send(pickle.dumps(r))
exceptExceptionase:
connection.send(pickle.dumps(e))
exceptExceptionase:
pass
defrpc_server(handler,address,authkey):
sock=Listener(address,authkey=authkey)
whileTrue:
client=sock.accept()
t=Thread(target=handler.handle_connection,args=(client,))
t.daemon=True
print("函數(shù)開始執(zhí)行")
t.start()
defadd(x,y):
returnx+y
defsub(x,y):
returnx-y
if__name__=='__main__':
print(format("開始加載RPC處理器",'》20'))
handler=RPCHandler()
print(format("處理器加載完成,注冊函數(shù)",'》20'))
handler.register_function(add)
handler.register_function(sub)
print(format("函數(shù)注冊成功,服務(wù)啟動",'》20'))
rpc_server(handler,('localhost',17000),authkey=b'peekaboo')
RPC客戶端
importpickle
frommultiprocessing.connectionimportClient
classRPCProxy:
def__init__(self,connection):
self._connection=connection
def__getattr__(self,name):
print("開始調(diào)用函數(shù)",name)
defdo_rpc(*args,**kwargs):
self._connection.send(pickle.dumps((name,args,kwargs)))
result=pickle.loads(self._connection.recv())
print("返回結(jié)果",result)
ifisinstance(result,Exception):
raiseresult
returnresult
returndo_rpc
c=Client(('localhost',17000),authkey=b'peekaboo')
print(format("建立連接,創(chuàng)建RPC代理",'》30'),c)
proxy=RPCProxy(c)
print(format("創(chuàng)建代理成功",'》30'))
print("add(2,3)=",proxy.add(2,3))
print("sub(2,3)=",proxy.sub(2,3))
D:\python\Python310\python.exeD:/python/code/rabbit_mq_demo/rpcserver.py
開始加載RPC處理器》》》》》》》》》》
處理器加載完成,注冊函數(shù)》》》》》》》》
函數(shù)注冊成功,服務(wù)啟動》》》》》》》》》
函數(shù)開始執(zhí)行
調(diào)用函數(shù):(add,(2,3),{})
返回結(jié)果:5
調(diào)用函數(shù):(sub,(2,3),{})
返回結(jié)果:-1
==============
D:\python\Python310\python.exeD:/python/code/rabbit_mq_demo/RPC.py
建立連接,創(chuàng)建RPC代理》》》》》》》》》》》》》》》》》》multiprocessing.connection.Connectionobjectat0x00DFACA0
創(chuàng)建代理成功》》》》》》》》》》》》》》》》》》》》》》》》
開始調(diào)用函數(shù)add
返回結(jié)果5
add(2,3)=5
開始調(diào)用函數(shù)sub
返回結(jié)果-1
sub(2,3)=-1
Processfinishedwithexitcode0
RPCHandler和RPCProxy的基本思路是很比較簡單的。
如果一個客戶端想要調(diào)用一個遠(yuǎn)程函數(shù),比如foo(1,2,z=3),代理類創(chuàng)建一個包含了函數(shù)名和參數(shù)的元組(foo,(1,2),{z:3})。這個元組被pickle序列化后通過網(wǎng)絡(luò)連接發(fā)生出去。
由于底層需要依賴pickle,那么安全問題就需要考慮了(因為一個聰明的黑客可以創(chuàng)建特定的消息,能夠讓任意函數(shù)通過pickle反序列化后被執(zhí)行)。
因此永遠(yuǎn)不要允許來自不信任或未認(rèn)證的客戶端的RPC。特別是絕對不要允許來自Internet的任意機(jī)器的訪問,這種只能在內(nèi)部被使用,位于防火墻后面并且不要對外暴露。
作為pickle的替代,也許可以考慮使用JSON、XML或一些其他的編碼格式來序列化消息。
例如,本機(jī)實例可以很容易的改寫成JSON編碼方案。還需要將pickle.1oads()和pickle.dumps()替換成json.1oads()和json.dumps()即可:
#hereputtheimportlib
importjson
........
defhandle_connection(self,connection):
try:
whileTrue:
#反序列化
func_name,args,kwargs=json.loads(connection.recv())
try:
print("調(diào)用函數(shù):",(func_name,args,kwargs))
r=self._functions[func_name](*args,**kwargs)
print("返回結(jié)果:",r)
#序列化發(fā)送
connection.send(json.dumps(r))
exceptExceptionase:
connection.send(json.dumps(e))
exceptExceptionase:
pass
......
importjson
frommultiprocessing.connectionimportClient
classRPCProxy:
def__init__(self,connection):
self._connection=connection
def__getattr__(self,name):
print("開始調(diào)用函數(shù)",name)
defdo_rpc(*args,**kwargs):
print("JSON序列化后的值",json.dumps((name,args,kwargs)))
self._connection.send(json.dumps((name,args,kwargs)))
result=json.loads(self._connection.recv())
print("返回結(jié)果",result)
ifisinstance(result,Exception):
raiseresult
returnr
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 光刻技術(shù)原理
- 2025年高職地圖數(shù)據(jù)圖例轉(zhuǎn)換技術(shù)(圖例轉(zhuǎn)換實操)試題及答案
- 2025年中職設(shè)備維護(hù)管理(管理技術(shù))試題及答案
- 2025年中職服裝與服飾設(shè)計(服飾教學(xué)實操)試題及答案
- 2025年高職房地產(chǎn)經(jīng)營與管理(房地產(chǎn)經(jīng)營與管理基礎(chǔ))試題及答案
- 2025年高職人力資源管理(招聘與配置)試題及答案
- 2025年高職河運海事管理(海事管理基礎(chǔ))試題及答案
- 2025年中職電子技術(shù)應(yīng)用(電子電路基礎(chǔ))試題及答案
- 2025年大學(xué)環(huán)境科學(xué)(水污染控制實驗)試題及答案
- 2025年中職第二學(xué)年(老年護(hù)理方向)照護(hù)實務(wù)階段測試題及答案
- 章節(jié)復(fù)習(xí):平行四邊形(5個知識點+12大常考題型)解析版-2024-2025學(xué)年八年級數(shù)學(xué)下冊(北師大版)
- 《實踐論》《矛盾論》導(dǎo)讀課件
- 中試基地運營管理制度
- 老年病康復(fù)訓(xùn)練治療講課件
- DB4201-T 617-2020 武漢市架空管線容貌管理技術(shù)規(guī)范
- 藥品追溯碼管理制度
- 腳手架國際化標(biāo)準(zhǔn)下的發(fā)展趨勢
- 購銷合同范本(塘渣)8篇
- 生鮮業(yè)務(wù)采購合同協(xié)議
- GB/T 4340.2-2025金屬材料維氏硬度試驗第2部分:硬度計的檢驗與校準(zhǔn)
- 銷售合同評審管理制度
評論
0/150
提交評論