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