Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当多组子进程同时运行时,关闭浏览器中的SSE连接会导致uWSGI中的segfault_Python_Segmentation Fault_Uwsgi_Server Sent Events - Fatal编程技术网

Python 当多组子进程同时运行时,关闭浏览器中的SSE连接会导致uWSGI中的segfault

Python 当多组子进程同时运行时,关闭浏览器中的SSE连接会导致uWSGI中的segfault,python,segmentation-fault,uwsgi,server-sent-events,Python,Segmentation Fault,Uwsgi,Server Sent Events,我正在构建一个web应用程序,用于处理约60000个(并不断增长)大文件,执行一些分析,并返回一个需要用户验证的“最佳猜测”。这些文件将按类别进行细化,以避免加载每个文件,但我仍然会遇到一种情况,即我可能一次要处理1000多个文件 这些文件都是大文件,每次处理可能需要8-9秒,在1000多个文件的情况下,让用户在审阅之间等待8秒或在处理文件之前等待2小时以上是不切实际的 为了克服这个问题,我决定使用多处理技术来产生几个worker,每个worker将从一个文件队列中选择、处理它们并插入到一个输出

我正在构建一个web应用程序,用于处理约60000个(并不断增长)大文件,执行一些分析,并返回一个需要用户验证的“最佳猜测”。这些文件将按类别进行细化,以避免加载每个文件,但我仍然会遇到一种情况,即我可能一次要处理1000多个文件

这些文件都是大文件,每次处理可能需要8-9秒,在1000多个文件的情况下,让用户在审阅之间等待8秒或在处理文件之前等待2小时以上是不切实际的

为了克服这个问题,我决定使用多处理技术来产生几个worker,每个worker将从一个文件队列中选择、处理它们并插入到一个输出队列中。我有另一种方法,它基本上轮询项目的输出队列,然后在有项目可用时将它们流式传输到客户端

在我们的环境中,我们将gevent与uWSGI和Django一起使用,我知道在gevent上下文中通过多处理创建子进程会在子进程中产生不希望的事件循环状态。在分叉之前生成的小绿细胞在子代中重复。因此,我决定使用来帮助处理子进程

这一切在不间断的情况下工作得很好。但是,如果用户在文件仍在处理时随时切换类别,我会关闭浏览器中的SSE连接并打开另一个连接,从而导致一组新的子进程生成并终止现有进程(或尝试创建)。这会导致两种情况中的一种发生

当我向客户端输出结果时,我从uWSGI获得一个
IOError
,因为连接已经关闭。我将整个函数包装在一个
try…finally
中,并在函数退出之前杀死所有工作人员

我可以在进程终止时阻止,也可以在后台执行。每种方法都有不同的结果。当尝试在不阻塞的情况下终止时,原始进程永远不会终止,新进程停止产生,任何对服务器的请求(来自任何页面)都会挂起,直到我手动终止所有uWSGI进程

阻塞时,uWSGI报告一个分段错误,主工作进程被终止并重新启动,终止所有新的和旧的子进程

用于打开/关闭连接的JavaScript示例:

var state={};
函数分析(){
//如果存在连接,请将其关闭。
if(state.evtSource){
state.evtSource.close();
}
//创建到服务器的新连接。
evtSource=state.evtSource=neweventsource(“?myarg=myval”);
evtSource.onmessage=函数(消息){
//做事
}
}
服务器端示例代码:

从项目导入项目
进口许可证
导入多处理
导入时间
最大工人数=10
#Worker位于ProcessFiles之外,因为``让``
#腌制目标。
def工人(项目):
返回项。进程()
类ProcessFiles(对象):
定义初始化(自):
self.input_queue=multiprocessing.queue()
self.output_queue=multiprocessing.queue()
self.file\u计数=0
self.pool=lets.ProcessPool(最大工人数)
def查询结果(自我):
#查询数据库中要处理的文件记录。
#返回结果并将self.file_计数设置为
#返回的记录数。
通过
def启动(自):
#将要处理的文件排队。
查找self中的结果。查询\u查找\u结果():
项目=项目(结果)
self.input\u queue.append(项)
#最多生成MAX_WORKERS子进程以进行分析
#输入队列中的所有项目。附加已处理文件
#输出队列。
对于self.input_队列中的项目:
self.pool.apply\u async(worker,args=(item,),callback=self.callback)
#轮询要发送到客户端的项目。
返回self.get_processed_items()
def回调(自处理):
self.output\u queue.put(已处理)
def get_processed_项目(自身):
#等待输出队列至少包含1项。
#当项目可用时,将其交给客户。
尝试:
计数=0
一边数数!=self.file\u计数:
尝试:
item=self.output\u queue.get(超时=1)
除:
#队列为空。等待并重试。
时间。睡眠(1)
持续
计数+=1
收益项目
收益率“结束”
最后:
#杀死所有子进程。

self.pool.kill(block=True)#除非您使用的是非常旧(且已损坏)的uWSGI版本,否则每个segfault都应该在日志中返回回溯。你能用uWSGI配置报告吗?