我有一个包含4个节点和主服务器的集群。主人派遣的工作可能需要30秒到15分钟才能结束。
节点正在使用SocketServer.TCPServer
进行侦听,在主节点中,我打开连接并等待作业结束。
def run(nodes, args):
pool = multiprocessing.Pool(len(nodes))
return pool.map(load_job, zip(nodes, args))
load_job
函数使用socket.sendall
发送数据,之后,它使用socket.recv
(数据需要很长时间才能到达)。
该程序运行良好,直到大约200或300个这些作业运行。当它中断时,socket.recv
收到一个空字符串,并且在我终止节点进程并再次运行它们之前不能再运行任何作业。
我应该如何等待数据到来?另外,pool
中的错误处理非常糟糕,因为它会从另一个进程中保存错误并显示没有正确的回溯和此错误重复不是很常见...
修改: 现在我认为这个问题与套接字无关:
经过一些研究,看起来我的节点正在开启许多进程(因为它们也在multiprocessing.Pool
中运行它们的工作)并且它们不会被关闭!
我发现这些SO问题(here和here)在守护进程中使用multiprocessing
时谈论僵尸进程(完全是我的情况!)。
我需要进一步了解这个问题,但是现在我要杀死节点并在一段时间后恢复它们。
答案 0 :(得分:3)
(我在编辑前回复了这个问题,因为我不明白你的意思)。
socket.recv
不是等待套接字数据的最佳方式。我知道的最好方法是使用select
模块(文档here)。在单个套接字上等待数据时最简单的用法是select.select([your_socket],[],[])
,但它当然可以用于更复杂的任务。
关于socket.recv
收到空字符串的问题;当套接字是TCP套接字时(就像你的情况一样),这意味着套接字已被对等体关闭。
造成这种情况的原因可能会有所不同,但重要的是要理解在此之后,您将不再接收来自此套接字的任何数据,因此您可以使用它做的最好的事情就是关闭它({ {1}})。如果您不希望它关闭,那么您应该在此处搜索问题。