您好,登錄后才能下訂單哦!
本篇內容介紹了“如何實現一個XML-RPC server/client”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
Minos是小米2013年開源的針對海量服務節點無法高效操作及統一配置管理的痛點,全新探索并研發的一套大型分布式部署及監控的系統。該系統基于supervisor XML-RPC實現分布式計算,支持跨地域、多節點部署服務。
上圖為Minos架構圖,客戶端對task節點的操作通過supervisor的XML-RPC完成。接下來我們談談什么是XML-RPC,它是如何工作的。
XML-RPC是一個遠程過程調用(遠端程序呼叫)(remote procedure call,RPC)的分布式計算協議,通過XML將調用函數封裝,并使用HTTP協議作為傳送機制。
[1]可以用Perl, Java, Python, C, C++, PHP和許多編程語言實現。實現適用于Unix,Windows和Macintosh。
XML-RPC是受兩個早期協議的啟發。一個是由Dave Winer設計的匿名RPC協議。(這就是為什么XML-RPC服務器通常安裝在/RPC2下。)另一個更重要的是SOAP協議的初稿。Dave Winer提供了豐富的XML-RPC歷史淵源,對XML-RPC和SOAP之間的關系感興趣的可自行查閱資料。
一個簡單的示例。
服務端代碼示例:(Python2.7 運行環境)
#-*- coding:utf-8 -*- from SimpleXMLRPCServer import SimpleXMLRPCServer from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler # 指定路徑 class RequestHandler(SimpleXMLRPCRequestHandler): rpc_paths = ('/RPC2',) # 構建server server = SimpleXMLRPCServer(("localhost", 8000), requestHandler=RequestHandler) server.register_introspection_functions() # 注冊pow函數 # pow.__name__為 pow函數的名稱 server.register_function(pow) # 注冊自定義函數 def adder_function(x,y): return x + y server.register_function(adder_function, 'add') # 注冊實例; # 實例的方法均發布為 XML-RPC的方法 class MyFuncs: def div(self, x, y): return x // y server.register_instance(MyFuncs()) # 啟動server server.serve_forever()
接下來客戶端將調用服務端的方法:
#-*- coding:utf-8 -*-import xmlrpclib s = xmlrpclib.ServerProxy('http://localhost:8000') print s.pow(2,3) # Returns 2**3 = 8print s.add(2,3) # Returns 5print s.div(5,2) # Returns 5//2 = 2# 打印服務端所有方法 print s.system.listMethods()
由此在部署系統中,構建supervisor XML-RPC的服務端,封裝對節點操作的方法,由客戶端遠程調用此方法,實現分布式部署。
不過,SimpleXMLRPCServer是一個單線程的服務器。這意味著,服務端同時收到多個客戶端發送的多個請求,必須等待第一個請求完成以后才能繼續。有個最直接的方法可以解決這個問題:
from SimpleXMLRPCServer import SimpleXMLRPCServer from SocketServer import ThreadingMixIn # 新增構建ThreadXMLRPCServer類 class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer): pass # 重新構建server server = ThreadXMLRPCServer(("localhost", 8000), requestHandler=RequestHandler,allow_none=True) #Forking and threading versions of each type of server can be created using the ForkingMixIn and ThreadingMixIn mix-in classes. For instance, a threading UDP server class is created as follows:[2] class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
閱讀ThreadingMixIn的源碼發現,ThreadingMixIn重寫了server類中調用的process_request方法。因此實現了server端多線程處理。
在我們實際應用中,當我們構建多個XML-RPC server的client,進行鏈式調用時,經常遇到httplib.CannotSendRequest的報警。
調用過程:
client -- calls -- SimpleXMLRPCServer’s functions -- calls --SimpleXMLRPCServer's functions -- do finish task
記過排查CannotSendRequest發生在當一個httplib.HTTPConnection被又一次新的“request”操作中斷。 所以,每個httplib.HTTPConnection.request必須以.getresponse()調用配對。 如果該配對被另一個請求操作中斷,第二請求將產生CannotSendRequest錯誤。 所以,類似如下請求,將會產生錯誤:
connection = httplib.HTTPConnection(...) connection.request(...) connection.request(...)
問題分析:
兩次調用都是serverproxy來構建的。只有在同時多次請求的時候出現了這個問題,應該是存在資源競爭條件。serverproxy在中間層被共享。
解決思路:
是讓每個線程創建自己的serverproxy。
解決方案:
在調用第一個SimpleXMLRPCServer的方法時構建下一次調用的鏈接。確保每個線程維護自己的serverproxy。
“如何實現一個XML-RPC server/client”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。