python - 在 Flask 中初始化全局数据连接的并发安全方式

标签 python multithreading flask

全局变量是not thread-safe or "process-safe"在 Flask 中。

但是,我需要打开每个工作人员将使用的服务的连接,例如 PubSub 客户端或 Cloud Storage 客户端。看起来这些仍然需要是全局的,以便应用程序中的任何函数都可以访问它们。为了延迟初始化它们,我检查变量是否为 None,这需要是线程安全的。打开每个请求将使用的连接的推荐方法是什么?我应该使用线程锁来同步吗?

最佳答案

The question you linked谈论的是数据,而不是连接。让多个工作人员改变全局数据并不好,因为您无法推断这些工作人员在 Web 应用程序中的位置以保持它们同步。

该问题的解决方案是使用外部数据源,如数据库,必须以某种方式连接到该数据源。但是,您拥有一个全局连接的想法并不安全,因为多个工作线程会同时与它交互,并且要么弄乱彼此的状态,要么一次等待一个来获取资源。处理此问题的最简单方法是在需要时在每个 View 中建立连接。


此示例展示了如何在没有全局变量的情况下为每个请求建立唯一连接,并在为请求建立连接后重新使用该连接。 g 对象,虽然它看起来像一个全局对象,但在幕后被实现为线程局部的,因此每个工作人员都有自己的 g 实例和存储在其上的连接只有一个请求。

from flask import g

def get_conn():
    """Use this function to establish or get the already established
    connection during a request. The connection is closed at the end
    of the request. This avoids having a global connection by storing
    the connection on the g object per request.
    """
    if "conn" not in g:
        g.conn = make_connection(...)

    return g.conn

@app.teardown_request
def close_conn(e):
    """Automatically close the connection after the request if
    it was opened.
    """
    conn = g.pop("conn", None)

    if conn is not None:
        conn.close()

@app.route("/get_data")
def get_data():
    # If something else has already used get_conn during the
    # request, this will return the same connection. Anything
    # that uses it after this will also use the same connection.
    conn = get_conn()
    data = conn.query(...)
    return jsonify(data)

一旦您有数千个并发请求,您最终可能会发现为每个请求建立一个新连接的成本太高。一种解决方案是建立一个连接池来全局存储一个连接列表,以线程安全的方式根据需要获取和替换列表中的连接。 SQLAlchemy(和 Flask-SQLAlchemy)使用这种技术。许多库已经提供了连接池的实现,所以要么使用它们,要么将它们作为您自己的引用。

关于python - 在 Flask 中初始化全局数据连接的并发安全方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54214967/

相关文章:

python - 如何读取 flask 中的多部分/表单数据

multithreading - 创建 BackgroundWorkers 的线程似乎将 Completed 事件排队

python - celery 服务器错误: "cannot mix new setting names with old setting names" while running the server

python - 如何在 AWS Elastic Beanstalk 上设置 HTTPS

jquery - 如何从 Django(Python) 接收 jQuery 列表

python - 如何让 Python 记住设置?

python - 从python语法错误中的相对路径导入

linux - 修改内核调度程序,为特定程序提供更长的时间片

c++ - Qt:使用一个连接从多个线程写入数据库

python - 如何使这个 Flask-mysql 插入提交?