部分ssrpc.py代码分析 -- 服务端:
1 #!/usr/bin/python3 2 3 from xmlrpc.client import Fault, dumps, loads 4 import sys 5 from socketserver import ForkingMixIn 6 from xmlrpc.server import SimpleXMLRPCServer 7 8 class VerboseFaultXMLRPCServer(SimpleXMLRPCServer): 9 def _marshaled_dispatch(self, data, dispatch_method = None, path = None): 10 """Dispatches an XML-RPC method from marshalled (XML) data. 11 12 XML-RPC methods are dispatched from the marshalled (XML) data 13 using the _dispatch method and the result is returned as 14 marshalled data. For backwards compatibility, a dispatch 15 function can be provided as an argument (see comment in 16 SimpleXMLRPCRequestHandler.do_POST) but overriding the 17 existing method through subclassing is the preferred means 18 of changing method dispatch behavior. 19 """ 20 21 try: 22 params, method = loads(data) 23 24 # generate response 25 if dispatch_method is not None: 26 response = dispatch_method(method, params) 27 else: 28 response = self._dispatch(method, params) 29 # wrap response in a singleton tuple 30 response = (response,) 31 response = dumps(response, methodresponse=1, 32 allow_none=self.allow_none, encoding=self.encoding) 33 except Fault as fault: 34 response = dumps(fault, allow_none=self.allow_none, 35 encoding=self.encoding) 36 except: 37 # report exception back to server 38 exc_type, exc_value, exc_tb = sys.exc_info() 39 while exc_tb.tb_next is not None: 40 exc_tb = exc_tb.tb_next # find last frame of the traceback 41 lineno = exc_tb.tb_lineno 42 code = exc_tb.tb_frame.f_code 43 filename = code.co_filename 44 name = code.co_name 45 response = dumps( 46 Fault(1, "%s:%s FILENAME: %s LINE: %s NAME: %s" % ( 47 exc_type, exc_value, filename, lineno, name)), 48 encoding=self.encoding, allow_none=self.allow_none, 49 ) 50 51 return response.encode(self.encoding) 52 53 # One process per request 54 class ForkingXMLRPCServer(ForkingMixIn, VerboseFaultXMLRPCServer): 55 max_children = 500 # default is 40 56 57 server = ForkingXMLRPCServer(("", 8889), allow_none=True) 58 59 # Register functions here 60 61 from ssapi.disk.sas import sasdiskinfo 62 from ssapi.disk.ledctl import ledctl_set 63 from ssapi.zfs.zpoollist import zpoollist 64 from ssapi.zfs.zpoolstatus import zpoolstatus 65 from ssapi.zfs.zpoolcreate import zpoolcreate 66 67 funcs = [ 68 sasdiskinfo, 69 ledctl_set, 70 zpoollist, 71 zpoolstatus, 72 zpoolcreate, 73 ] 74 75 for i in funcs: 76 server.register_function(i) 77 78 # Start service 79 server.serve_forever()
正如上篇文章所述,SimpleXMLRPCServer是一个单线程的服务器,所以这里支持多进程的方式如下:
1.定义VerboseFaultXMLRPCServer类,继承于SimpleXMLRPCServer
2.定义一个新类:ForkingXMLRPCServer(ForkingMixIn, VerboseFaultXMLRPCServer),其中ForkingMixIn是从socketserver中导入
3.调用新类创建server实体,server = ForkingXMLRPCServer(("", 8889), allow_none=True),则支持多进程
/usr/lib/python3.2/xmlrpc/server.py 中SimpleXMLRPCServer源代码:
1 class SimpleXMLRPCServer(socketserver.TCPServer, 2 SimpleXMLRPCDispatcher): 3 """Simple XML-RPC server. 4 5 Simple XML-RPC server that allows functions and a single instance 6 to be installed to handle requests. The default implementation 7 attempts to dispatch XML-RPC calls to the functions or instance 8 installed in the server. Override the _dispatch method inherited 9 from SimpleXMLRPCDispatcher to change this behavior. 10 """ 11 12 allow_reuse_address = True 13 14 # Warning: this is for debugging purposes only! Never set this to True in 15 # production code, as will be sending out sensitive information (exception 16 # and stack trace details) when exceptions are raised inside 17 # SimpleXMLRPCRequestHandler.do_POST 18 _send_traceback_header = False 19 20 def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler, 21 logRequests=True, allow_none=False, encoding=None, bind_and_activate=True): 22 self.logRequests = logRequests 23 24 SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding) 25 socketserver.TCPServer.__init__(self, addr, requestHandler, bind_and_activate) 26 27 # [Bug #1222790] If possible, set close-on-exec flag; if a 28 # method spawns a subprocess, the subprocess shouldn‘t have 29 # the listening socket open. 30 if fcntl is not None and hasattr(fcntl, ‘FD_CLOEXEC‘): 31 flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD) 32 flags |= fcntl.FD_CLOEXEC 33 fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
Tornado/Python 学习笔记(二)
时间: 2024-10-20 20:12:54