Concurrency-safe Way To Initialize Global Data Connections In Flask
Solution 1:
The question you linked is talking about data, not connections. Having multiple workers mutating global data is not good because you can't reason about where those workers are in a web application to keep them in sync.
The solution to that question is to use an external data source, like a database, which must be connected to somehow. Your idea to have one global connection is not safe though, since multiple worker threads would interact with it concurrently and either mess with each other's state or wait one at a time to acquire the resource. The simplest way to handle this is to establish a connection in each view when you need it.
This example shows how to have a unique connection per request, without globals, reusing the connection once it's established for the request. The g
object, while it looks like a global, is implemented as a thread-local behind the scenes, so each worker gets it's own g
instance and connection stored on it during one request only.
from flask import g
defget_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"notin g:
g.conn = make_connection(...)
return g.conn
@app.teardown_requestdefclose_conn(e):
"""Automatically close the connection after the request if
it was opened.
"""
conn = g.pop("conn", None)
if conn isnotNone:
conn.close()
@app.route("/get_data")defget_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)
You might eventually find that establishing a new connection each request is too expensive once you have many thousands of concurrent requests. One solution is to build a connection pool to store a list of connections globally, with a thread-safe way to acquire and replace a connection in the list as needed. SQLAlchemy (and Flask-SQLAlchemy) uses this technique. Many libraries already provide connection pool implementations, so either use them or use them as a reference for your own.
Post a Comment for "Concurrency-safe Way To Initialize Global Data Connections In Flask"