我们有一个使用 Python 和多处理的 Lambda 函数。任务被分成多个块,每个块被委托给一个子任务。当子进程完成时,它通过共享连接(管道)发送()结果。 父级等待所有子级完成(join()),然后在所有管道上执行recv()。
直到上个月一切都很顺利。现在,在每次第一次 Lambda 尝试时,第一个父级 recv() 都会收到 EOFError,这会导致我们的 Lambda 执行失败。奇怪的是,第二次尝试时,一切正常。
子代码以此结束:
conn.send([csv_data])
conn.close()
父代码在recv()上失败
for process in processes:
process.join()
csv_data = parent_connections[0].recv()[0]
父连接和子连接是管道的末端:
parent_conn, child_conn = Pipe()
我们看到的异常:
: EOFError
...
csv_data = parent_connections[0].recv()[0]
File "/var/lang/lib/python3.6/multiprocessing/connection.py", line 250, in recv
buf = self._recv_bytes()
File "/var/lang/lib/python3.6/multiprocessing/connection.py", line 407, in _recv_bytes
buf = self._recv(4)
File "/var/lang/lib/python3.6/multiprocessing/connection.py", line 383, in _recv
raise EOFError
EOFError
当我们尝试将读取从第一个父连接移动到 try/catch 中以查看问题是否仅存在于第一次读取时。
for i in range(0, len(parent_connections)):
try:
result_from_child = parent_connections[i].recv()[0]
except Exception as e:
print("Exception while processing data from a child process: {}.".format(str(e)))
在此更改之后,我们注意到前 N 次读取总是失败,而之后的所有读取都成功。
任何帮助将不胜感激:
为什么最近(上个月)才开始发生?也许 Lambda 基础设施有一些变化?
为什么它只在第一次 Lambda 尝试时发生?第二次尝试总是成功(第一次总是失败)。
每个块都有固定的大小,并且随着总工作量的增加,创建的进程总数也在增加。问题可能与此有关吗?
家长收到响应后关闭孩子连接解决了我的问题。
为什么会发生这种情况? - 疯狂的猜测
我最好的猜测是,第一次调用 lambda 时,通过管道进行通信会出现延迟。由于子级在父级接收之前关闭连接,因此会引发 EOFError。
解决方案
将所有子连接存储在列表中(就像父连接一样)并在父收到响应后关闭相应的子连接。
修改子代码
child.send(data)
修改父代码
results[i] = parent_connections[i].recv()
child_connections[i].close()