覆盖 class 变量和并发 Flask 请求

Overwriting class variable and concurrent Flask requests

我是 运行 一个 python Flask 服务器来执行棘手的算法,其中之一是将电缆分配给管道。

class Tube:
    max_capacity = 5
    cables: List[str]

    def has_capacity(self):
        return len(self.cables) < self.max_capacity

最大容量一直是 5 根,但现在有一位新客户实际拥有可容纳 6 根电缆的管子。
当我收到请求时,我现在只设置 Tube.max_capacity = request.args.get('max_capacity', 5)。然后每个 Tube 实例都会有正确的设置。

我想知道如果同时处理多个请求,这是否会继续工作?
Flask(我使用 Gunicorn 作为 WSGI)进程是否相互独立,这样可以安全地进行?我不想以奇怪的错误结束,因为最大容量在一个请求的中途发生了变化,因为另一个请求进来了。

编辑: 我试过了,它似乎按预期工作:

@app.route('/concurrency')
def concurrency():
    my_value = randint(0, 100)
    Concurrency.value = my_value
    time.sleep(8)
    return f"My value: {my_value} should be equal to Concurrency.value {Concurrency.value}"


class Concurrency:
    value = 10

不过,我想知道更多关于多个 Flask/Gunicorn 请求如何工作的信息。

WSGI 应用程序通常使用多个进程提供服务——最终在不同的服务器上——来自同一用户的请求将由第一个可用进程处理。 IOW:你 NOT 想要在每个请求的基础上更改任何模块或 class 级别变量,这是 **保证* 搞砸一切。

在没有更多上下文的情况下,不可能准确地告诉您如何解决问题,但在所有情况下,您都必须重新考虑您的设计。

编辑:

how do processes behave? If one of them sets the value, does another process see that value as well?

当然不是 - each process is totally isolated from the others - 因此更改模块级变量或 class 属性只会影响当前进程。但是由于进程不依赖于客户端(哪个进程将处理给定的请求是完全不可预测的),如果下一个请求由另一个进程提供服务,则一个进程中的此类更改不一定会在下一个请求中看到。和:

Or, is a process re-used, and then still has the value from the previous request?

进程当然会被重用,但这并不意味着同一进程将被同一用户的下一个请求重用——这是问题的第二部分:服务时 另一个 用户,您的进程仍将使用前一个用户的 "updated" max_capacity 值。

IOW,你所做的是 保证所有 用户的一切都搞砸了。这就是为什么我们使用外部(进程外)方式在请求之间存储和共享每个用户的数据 - 会话(用于易失性数据)或数据库(用于永久存储)。