simpleXMLRPC 服务器 python
我对 simpleXMLRPC 服务器有疑问。 我的程序中有一个服务器,可以从另一台服务器访问它。我们将拥有 simpleXMLServer 实例的计算机称为服务器,将另一台服务器称为客户端。
因此,当客户端连接到我的服务器时,服务器会调用服务器中的函数。此函数有时可能需要很长时间才能执行(最多 5 分钟),然后发送一条长消息。
class Report(object):
__instance = None
def __new__(self):
if self.__instance is None:
self.__instance = object.__new__(self)
self.__instance.__init()
return self.__instance
def __init(self):
self._lastRequestTime = 0
self._lastRequest = ''
self._minInterval = 1
self._timeout = 2
self.__lock = Utils.Threading.Lock()
self.__lockEvent = Utils.Threading.Lock()
self._event = Utils.Threading.Event()
reportThread = threading.Thread(name = 'reportThread',
target = self.reportLoop)
reportThread.start()
def _reportAll(self):
tmp = Somewhere.reportAll()
try:
self.__lock.acquire()
self._lastRequest = tmp
finally:
self.__lock.release()
def reportLoop(self):
while 1:
self._event.wait()
self._reportAll()
try:
self.__lockEvent.acquire()
self._event.clear()
finally:
self.__lockEvent.release()
def reportAll(self):
if abs(Utils.Time.time() - self._lastRequestTime) > self._minInterval or len(self._lastRequest) == 0:
self._lastRequestTime = time.time()
else:
return self._lastRequest
try:
self.__lockEvent.acquire()
self._event.set()
finally:
self.__lockEvent.release()
try:
self.__lock.acquire()
return self._lastRequest
finally:
self.__lock.release()
以下是我创建服务器的方式:
def startListen(self):
logging.basicConfig(level = logging.DEBUG)
try:
# Create server
self._server = SimpleXMLRPCServer(("192.168.0.57", 49007), requestHandler=RequestHandler)
self._server.register_introspection_functions()
self._server.register_function(Report().reportAll, 'reportAll')
self._server.serve_forever()
except:
return self.restart()
为了避免客户端服务器中的长时间等待(这可能会冻结客户端程序),我在客户端的服务器中创建了一个信号,该信号会停止客户端的线程,无论 5 秒后发生什么(我的客户端)实际上是 ganglia 守护进程 gmond 的一个实例)。这是客户端的代码:
def getMessage(self):
def timeoutHandler(signum, frame):
raise Exceptions.BFException('Timeout %d s lasted' % defaultTimeout)
self._client = None
msg = None
# To be sure that will not freeze, we set a signal
signal.signal(signal.SIGALRM, timeoutHandler)
signal.alarm(defaultTimeout)
try:
self._client = xmlrpclib.ServerProxy('http://192.168.0.57:49007')
msg = self._client.reportAll()
except:
print 'The connection has not been established'
self._client = None
msg = None
finally:
signal.alarm(0)
return msg
但是,无论我做什么,有时它会完全冻结并且我会收到该错误:
Exception happened during processing of request from ('192.168.0.85', 55417)
Traceback (most recent call last):
File "C:\Python26\lib\SocketServer.py", line 283, in _handle_request_noblock
self.process_request(request, client_address)
File "C:\Python26\lib\SocketServer.py", line 309, in process_request
self.finish_request(request, client_address)
File "C:\Python26\lib\SocketServer.py", line 322, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Python26\lib\SocketServer.py", line 617, in __init__
self.handle()
File "C:\Python26\lib\BaseHTTPServer.py", line 329, in handle
self.handle_one_request()
File "C:\Python26\lib\BaseHTTPServer.py", line 323, in handle_one_request
method()
File "C:\Python26\lib\SimpleXMLRPCServer.py", line 491, in do_POST
self.wfile.write(response)
File "C:\Python26\lib\socket.py", line 318, in write
self.flush()
File "C:\Python26\lib\socket.py", line 297, in flush
self._sock.sendall(buffer(data, write_offset, buffer_size))
error: [Errno 10053] Une connexion établie a été abandonnée par un logiciel de votre ordinateur hôte
如果我在 Debian 发行版中执行相同的操作,我会收到相同的错误,除了我得到:[Errno 32]管道破裂。
无论我做什么,如果再次调用该服务器,我总是在第一次收到此错误后收到此错误,并且根本没有响应。 我不知道该如何处理。我已经被困了几天了......
有人可以帮助我吗?
谢谢
I have an issue with the simpleXMLRPC server.
I have a server in my program which can be reachable from another server. Let's call server the computer which has an instance of simpleXMLServer and client the other server.
So when the client connect to my server, the server call a function in the server. This function can sometimes take long time to execute (to 5 minutes) and then send a long message.
class Report(object):
__instance = None
def __new__(self):
if self.__instance is None:
self.__instance = object.__new__(self)
self.__instance.__init()
return self.__instance
def __init(self):
self._lastRequestTime = 0
self._lastRequest = ''
self._minInterval = 1
self._timeout = 2
self.__lock = Utils.Threading.Lock()
self.__lockEvent = Utils.Threading.Lock()
self._event = Utils.Threading.Event()
reportThread = threading.Thread(name = 'reportThread',
target = self.reportLoop)
reportThread.start()
def _reportAll(self):
tmp = Somewhere.reportAll()
try:
self.__lock.acquire()
self._lastRequest = tmp
finally:
self.__lock.release()
def reportLoop(self):
while 1:
self._event.wait()
self._reportAll()
try:
self.__lockEvent.acquire()
self._event.clear()
finally:
self.__lockEvent.release()
def reportAll(self):
if abs(Utils.Time.time() - self._lastRequestTime) > self._minInterval or len(self._lastRequest) == 0:
self._lastRequestTime = time.time()
else:
return self._lastRequest
try:
self.__lockEvent.acquire()
self._event.set()
finally:
self.__lockEvent.release()
try:
self.__lock.acquire()
return self._lastRequest
finally:
self.__lock.release()
Here is how I create the server :
def startListen(self):
logging.basicConfig(level = logging.DEBUG)
try:
# Create server
self._server = SimpleXMLRPCServer(("192.168.0.57", 49007), requestHandler=RequestHandler)
self._server.register_introspection_functions()
self._server.register_function(Report().reportAll, 'reportAll')
self._server.serve_forever()
except:
return self.restart()
To avoid a long wait in the client server (that could make freeze the client program), I created a signal in my client's server that stop the thread of the client whatever happens after 5 seconds (my client is in fact an instance the daemon gmond of ganglia). That is the code of the client:
def getMessage(self):
def timeoutHandler(signum, frame):
raise Exceptions.BFException('Timeout %d s lasted' % defaultTimeout)
self._client = None
msg = None
# To be sure that will not freeze, we set a signal
signal.signal(signal.SIGALRM, timeoutHandler)
signal.alarm(defaultTimeout)
try:
self._client = xmlrpclib.ServerProxy('http://192.168.0.57:49007')
msg = self._client.reportAll()
except:
print 'The connection has not been established'
self._client = None
msg = None
finally:
signal.alarm(0)
return msg
However whatever I do, sometimes it freezes completely and I get that error :
Exception happened during processing of request from ('192.168.0.85', 55417)
Traceback (most recent call last):
File "C:\Python26\lib\SocketServer.py", line 283, in _handle_request_noblock
self.process_request(request, client_address)
File "C:\Python26\lib\SocketServer.py", line 309, in process_request
self.finish_request(request, client_address)
File "C:\Python26\lib\SocketServer.py", line 322, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Python26\lib\SocketServer.py", line 617, in __init__
self.handle()
File "C:\Python26\lib\BaseHTTPServer.py", line 329, in handle
self.handle_one_request()
File "C:\Python26\lib\BaseHTTPServer.py", line 323, in handle_one_request
method()
File "C:\Python26\lib\SimpleXMLRPCServer.py", line 491, in do_POST
self.wfile.write(response)
File "C:\Python26\lib\socket.py", line 318, in write
self.flush()
File "C:\Python26\lib\socket.py", line 297, in flush
self._sock.sendall(buffer(data, write_offset, buffer_size))
error: [Errno 10053] Une connexion établie a été abandonnée par un logiciel de votre ordinateur hôte
If I do the same in a Debian distribution, I get the same error except that I get : [Errno 32] Broken Pipe.
And whatever I do, if a call again this server I always get this error after getting a first time this error, and no response at all.
I don't know how to deal with that. I have been stuck for few days on that...
Could anyone help me please ?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
基本上,您正在终止客户端的连接,因此服务器报告连接已终止。
我不确定为什么之后没有得到任何响应,但需要考虑的一件事是服务器是单线程的,因此当缓慢的操作正在进行时,无法处理其他连接。
另请注意,信号可能不会传递到与调用
signal()
相同的线程,因此这可能会给您带来问题,除非 python 在幕后做了一些魔法来确保通知正确的线程。同样,我不确定抛出异常是否普遍允许,当然,从 C 语言来看,你不应该期望总是在主堆栈上。Basically you are killing the client's connection, so the server is reporting the connection has been terminated.
I'm not sure why you're getting no response after that, but one thing to consider is that the server is single-threaded, so while the slow operation is underway no other connections can be processed.
Also note that the signal may not be delivered to the same thread as the call to
signal()
, so that might cause you problems, unless python does some magic behind the scenes to ensure the correct thread is notified. Similarly, I'm not sure if throwing an exception is universally allowed, certainly, from C, you shouldn't expect to always be on the main stack.为什么不在客户端计算机上运行一个 simpleXMLRPC 服务器并使用工作线程和队列实现原始服务器。您的原始服务器会将参数推送到队列并立即返回。工作线程等待队列并在数据可用时执行。完成后,它将数据作为远程过程调用的参数发送回客户端,其方式与从客户端接收调用的方式完全相同。
这样做意味着客户端和服务器都不会阻塞。
Why not run a simpleXMLRPC server on the client machine as well and implement your original server with a worker thread and a queue. Your original server would push the arguments to the queue and immediately return. The worker thread waits on the queue and executes when data is available. When it has finished it sends the data back to the client as arguments to a remote procedure call in exactly the same way as it received the call from the client.
Doing it this way means that neither the client nor the server will block.