如何在多线程模式下使用 Gunicorn 运行 Flask

Posted

技术标签:

【中文标题】如何在多线程模式下使用 Gunicorn 运行 Flask【英文标题】:How to run Flask with Gunicorn in multithreaded mode 【发布时间】:2016-06-20 15:38:36 【问题描述】:

我有用 Flask 编写的 Web 应用程序。正如大家所建议的,我不能在生产中使用 Flask。所以我想到了Gunicorn with Flask

在 Flask 应用程序中,我正在加载一些机器学习模型。它们的总大小为 8GB。我的 Web 应用程序的并发性可以达到 1000 个请求。机器内存为15GB。 那么运行这个应用程序的最佳方式是什么?

【问题讨论】:

看到这个已经很老了,但是你能告诉我们你最后用的是什么吗?目前有同样的情况.. 有解决办法吗? @neel 【参考方案1】:

您可以使用 Gunicorn 使用多个工作人员或异步工作人员启动您的应用程序。

烧瓶服务器.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()

带有 gevent 异步工作者的 Gunicorn

gunicorn server:app -k gevent --worker-connections 1000

Gunicorn 1 worker 12 个线程:

gunicorn server:app -w 1 --threads 12

Gunicorn 有 4 个工人(多处理):

gunicorn server:app -w 4

这篇文章中有关 Flask 并发的更多信息:How many concurrent requests does a single Flask process receive?。

【讨论】:

如果有多个工作人员,由于模型的大小很大,它会抛出内存不足异常。我认为每个工人都会将所有模型加载到不同的内存空间中 你需要使用像 gevent 这样的异步工作者来允许与一个工作者并发:gunicorn -k gevent --worker-connections 1000 您还可以添加--threads 以使用指定的线程数运行每个worker。请参阅编辑。 如果我的 api 调用大约需要 1 秒,我应该使用哪种工作类型? 我将使用 gevent 和猴子补丁你的应用程序:***.com/questions/29527351/…。你也可以看看 celery 来运行后台任务。【参考方案2】:

最好的办法是使用 pre-fork 模式 (preload_app=True)。这将在“主”进程中初始化您的代码,然后简单地分叉工作进程来处理请求。如果您在 linux 上运行并假设您的模型是只读的,那么操作系统足够智能,可以在所有进程中重用物理内存。

【讨论】:

我发现的问题是,如果您正在运行数据库,他们会抱怨数据库实例不应该被分叉。就我而言,来自 pyMongo 的 MongoClient /usr/local/lib/python3.8/site-packages/pymongo/topology.py:164: UserWarning: MongoClient opened before fork. Create MongoClient only after forking. 是的,在这些情况下,您需要确保在分叉后初始化这些连接。之后应该没问题。

以上是关于如何在多线程模式下使用 Gunicorn 运行 Flask的主要内容,如果未能解决你的问题,请参考以下文章

单例模式在多线程下的问题

gunicorn + Flask架构中使用多进程全局锁

Django 是两次初始化视图

Gunicorn 在多处理进程和工作进程之间共享内存

单例模式在多线程下的多种实现模式

设计模式 - 单例模式之多线程调试与破坏单例