系统相关
首页 > 系统相关> > python – 拥有子进程允许rpc-server在子进程存活时重新启动

python – 拥有子进程允许rpc-server在子进程存活时重新启动

作者:互联网

脚本

我有一个rpc-server需要产生持续数天的重要进程(multiprocessing.Process).出于安全/安全的原因,我不希望这些进程生存依赖于rpc-server.因此,我希望服务器能够在流程运行时能够重启并能够重启.

孤儿进程

这个问题是可以解决的(不要粘贴它你不想放弃以前的工作,它将关闭你的python会话):

import os
import multiprocessing
import time

def _job(data):
    for _ in range(3):
        print multiprocessing.current_process(), "is working"
        time.sleep(2)
    print multiprocessing.current_process(), "is done"

#My real worker gets a Connection-object as part of a
#multiprocessing.Pipe among other arguments
worker = multiprocessing.Process(target=_job, args=(None,))
worker.daemon = True
worker.start()
os._exit(0)

问题:如果worker工作,则关闭rpc-server的套接字

退出主进程似乎没有帮助或影响socket问题的关闭.因此,为了说明服务器重新启动的问题,在第一个服务器关闭后启动第二个具有相同参数的服务器进行模拟.

以下工作完美:

import SimpleXMLRPCServer
HOST = "127.0.0.1"
PORT = 45212
s = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT))
s.server_close()
s = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT))
s.server_close()

但是,如果创建了一个worker,它会引发一个socket.error,说套接字已被使用:

s = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT))
worker = multiprocessing.Process(target=_job, args=(None,))
worker.start()
s.server_close()
s = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT)) #raises socket.error
worker.join()
s.server_close()

手动关闭服务器套接字确实有效:

import socket
s = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT))
worker = multiprocessing.Process(target=_job, args=(None,))
worker.start()
s.socket.shutdown(socket.SHUT_RDWR)
s = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT))
worker.join()
s.server_close()

但这种行为真让我担心.我没有以任何方式将套接字传递给worker,但无论如何它似乎都得到了它.

之前发布过类似的问题,但是它们倾向于将套接字传递给工作者,而这里并不打算这样做.如果我发送套接字,我可以在工作中关闭它并绕过关闭hack:

def _job2(notMySocket):
    notMySocket.close()
    for _ in range(3):
        print multiprocessing.current_process(), "is working"
        time.sleep(2)
    print multiprocessing.current_process(), "is done"

s = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT))
worker = multiprocessing.Process(target=_job2, args=(s.socket,))
worker.start()
time.sleep(0.1) #Just to be sure worker gets to close socket in time
s.server_close()
s = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT)) 
worker.join()
s.server_close()

但服务器的套接字绝对没有理由访问该工作者.我不喜欢这个解决方案,即使它是迄今为止最好的解决方案.

有没有办法限制使用多处理时分叉的内容.过程只有我想要传递给目标的东西才被复制,而不是所有打开的套接字和其他内容?

在我的情况下,要使此代码工作:

s = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT))
childPipe, parentPipe = multiprocessing.Pipe()
worker = multiprocessing.Process(target=_job, args=(childPipe,))
worker.start()
s.server_close()
s = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT)) #raises socket.error
worker.join()
s.server_close()

解决方法:

如果您使用的是Python 2.x,我认为没有办法在Posix平台上避免这种继承. os.fork将始终用于创建新进程,这意味着父进程的整个状态将被复制到子进程.您所能做的就是立即关闭孩子的插座,这就是您已经在做的事情.避免这种继承的唯一方法是在启动服务器之前启动进程.您可以通过提前启动Process然后使用multiprocessing.Queue来传递工作项(而不是args关键字参数)或multiprocessing.Event来指示它应该实际开始工作.根据您需要发送给子进程的内容,您的用例实际上可能会或可能不会实现.

但是,如果您使用的是Python 3.4(或者可以迁移到3.4),则可以使用spawn or forkserver contexts来避免继承套接字.

spawn

The parent process starts a fresh python interpreter process.
The child process will only inherit those resources necessary to run
the process objects run() method. In particular, unnecessary file
descriptors and handles from the parent process will not be inherited.
Starting a process using this method is rather slow compared to using
fork or forkserver.

Available on Unix and Windows. The default on Windows.

forkserver

When the program starts and selects the forkserver start
method, a server process is started. From then on, whenever a new
process is needed, the parent process connects to the server and
requests that it fork a new process. The fork server process is single
threaded so it is safe for it to use os.fork(). No unnecessary
resources are inherited.

例:

def _job2():
    for _ in range(3):
        print multiprocessing.current_process(), "is working"
        time.sleep(2)
    print multiprocessing.current_process(), "is done"

ctx = multiprocessing.get_context('forkserver')
worker = ctx.Process(target=_job2)
worker.start()

标签:python,linux,sockets,multiprocessing,simplexmlrpcserver
来源: https://codeday.me/bug/20190708/1403652.html