Flask 线程=适用于烧瓶插座

Flask 线程=适用于烧瓶插座,flask,flask-socketio,Flask,Flask Socketio,我一直在使用flask,我的一些路由处理程序开始计算,可能需要几分钟才能完成。使用flask的开发服务器,我可以使用app.run(threaded=True),我的服务器在停止执行这些多分钟计算时将继续响应其他请求 现在我已经开始使用Flask SocketIO,我不知道如何做同样的事情。我知道我可以在python中显式地生成一个单独的线程,只要它开始其中一个计算。这是唯一的办法吗?或者对于flask socketio是否存在与threaded=True等效的内容。(或者,更可能的是,我完全糊

我一直在使用flask,我的一些路由处理程序开始计算,可能需要几分钟才能完成。使用flask的开发服务器,我可以使用app.run(threaded=True),我的服务器在停止执行这些多分钟计算时将继续响应其他请求

现在我已经开始使用Flask SocketIO,我不知道如何做同样的事情。我知道我可以在python中显式地生成一个单独的线程,只要它开始其中一个计算。这是唯一的办法吗?或者对于flask socketio是否存在与threaded=True等效的内容。(或者,更可能的是,我完全糊涂了。)


感谢您的帮助。

Flask/Werkzeug中线程模式的思想是使开发服务器能够同时处理多个请求。在默认模式下,服务器一次可以处理一个请求,如果客户端在服务器已在处理前一个请求时发送请求,则第二个请求必须等待,直到第一个请求完成。在线程模式下,Werkzeug为每个传入请求生成一个线程,因此多个请求被并发处理。显然,您正在利用线程模式来处理需要很长时间才能返回的请求,同时保持服务器对其他请求的响应

请注意,当您从开发web服务器迁移到生产web服务器时,这种方法很难正确扩展。对于基于工作者的服务器,您必须选择固定数量的工作者,这将为您提供最大的并发请求数

另一种方法是使用基于协同路由的服务器,如gevent,它完全受Flask支持。对于gevent,有一个工作进程,但其中有多个轻量级(或“绿色”)线程,它们协同允许彼此运行。在这个模型下工作的关键是确保这些绿色线程不会滥用它们获得的CPU时间,因为一次只能运行一个线程。如果这项工作做得好,服务器的可扩展性将比我上面描述的多工作方法好得多,并且您可以轻松地以这种方式处理数百/数千个客户机

现在您想要使用Flask SocketIO,这个扩展需要使用gevent。如果这个需求的原因不清楚,那么与HTTP请求不同,SocketIO使用WebSocket协议,这需要长时间的连接。使用gevent和green线程可以拥有大量潜在的持续连接的客户端,这对于多个工作者来说是不可能的

问题在于计算时间长,这对gevent类型的服务器不友好。要使其工作,您需要确保计算函数经常产生,以便其他线程有机会运行而不会饿死。例如,如果计算函数中有一个循环,则可以执行以下操作:

def my_long_calculation():
    while some_condition:
        # do some work here

        # let other threads run
        gevent.sleep()
sleep()。最终控制权将返回给您的函数,此时它将进入下一次迭代。您需要确保睡眠调用的间隔不要太大(因为这会使应用程序的其余部分没有响应)或太近(因为这可能会降低计算速度)

因此,为了回答您的问题,只要您在长时间的计算中正确地让步,就不需要做任何特殊的事情来处理并发请求,因为这是gevent的正常操作模式

如果出于任何原因,收益率方法是不可能的,那么您可能需要考虑将CPU密集型任务卸载到另一个进程。也许可以用芹菜把它们做成工作队列


对不起,我的回答太冗长了。希望这有帮助

非常感谢你的回复,米格尔。(我本想早点谢谢你,但我去度假了。)这是一个非常明显的帮助。