在 Gunicorn / Flask 应用程序中的进程之间共享静态全局数据

Posted

技术标签:

【中文标题】在 Gunicorn / Flask 应用程序中的进程之间共享静态全局数据【英文标题】:Sharing static global data among processes in a Gunicorn / Flask app 【发布时间】:2014-11-10 22:57:32 【问题描述】:

我有一个在 Gunicorn 下运行的 Flask 应用程序,使用带有 20 个工作进程的同步工作程序类型。该应用程序在启动时会读取大量数据,这需要时间并占用内存。更糟糕的是,每个进程都会加载自己的副本,这会导致它花费更长的时间并占用 20 倍的内存。数据是静态的,不会改变。我想加载一次并让所有 20 名工作人员共享它。

如果我使用preload_app 设置,它只在一个线程中加载,最初只占用 1X 内存,但一旦请求开始进入,它似乎会膨胀到 20X。我需要快速随机访问数据,所以我宁愿不做IPC。

有没有办法在 Gunicorn 进程之间共享静态数据?

【问题讨论】:

【参考方案1】:

内存映射文件将允许您在进程之间共享页面。

https://docs.python.org/3/library/mmap.html

请注意,内存消耗统计数据通常具有误导性且无用。通常最好考虑 vmstat 的输出,看看是否交换了很多。

【讨论】:

我想应该说我想共享一个普通的 Python 字典,而不仅仅是一块内存。 @DoctorJ 那你倒霉了。原因是 Python 数据结构只是指向内存中指针的指针,它将跨越许多页。大多数这些页面也将与写入的数据共享,因此写时复制会导致页面在每个进程中被复制。我建议使用像 Redis 这样的对象存储或键值存储——这是当今这个问题的“标准”解决方案。 localhost 上的 IPC 非常快,如果您认为它会成为瓶颈,您可能会过早优化。【参考方案2】:

假设您的首要任务是将数据保留为 Python 数据结构,而不是将其移动到 Redis 等数据库,那么您将不得不进行更改,以便您可以为服务器使用单个进程。

Gunicorn 可以与 gevent 一起使用协程创建一个可以在单个工作进程中支持多个客户端的服务器,这可能是满足您需求的一个不错的选择。

【讨论】:

你能解释一下吗?这听起来可能很有价值,但我不确定它会如何工作。 其实并没有太大的区别,Flask 将你从细节中抽象出来。当你使用 gevent 时,你只需要确保你的视图函数能做他们需要做的事情,而不需要花费大量的 CPU 时间(或者如果它们是冗长的任务,则产生)。多任务处理是通过将每个请求放在一个协程中来实现的,但这一切都由框架处理。 我的意思是让代码仅在生成数据并保持更新的父进程中运行。非常类似于这个问题:***.com/questions/13768894/… 当你使用gevent、eventlet或其他协程框架时,只有一个进程,没有父进程和子进程。在流程开始时,您可以加载或生成所需的任何数据并将其放在全局范围内,所有处理程序都可以访问这些数据,因为它们都在同一个流程中运行。由于数据是静态的(至少在这个问题中是这样),您甚至不必担心锁定。 @Miguel 是否有任何性能差异 btw gevent 进程和其他选择,如 gunicorn 中的龙卷风进程

以上是关于在 Gunicorn / Flask 应用程序中的进程之间共享静态全局数据的主要内容,如果未能解决你的问题,请参考以下文章

gunicorn Flask 应用程序在 Docker 中挂起

如何使用 Flask-Script 和 Gunicorn

调试在 Gunicorn 中运行的 Flask 应用程序

gunicorn部署Flask服务

Kubernetes 和 Gunicorn 上的 Flask 应用程序扩展

Flask 应用程序退出时如何停止 Gunicorn