如何确保与uWSGI和Pyramid的唯一SQLAlchemy数据库连接

时间:2016-11-28 00:45:59

标签: python sqlalchemy thread-safety pyramid uwsgi

我有这个金字塔应用程序:

from pyramid.config import Configurator
from pyramid.response import Response

from sqlalchemy import create_engine
from sqlalchemy.pool import QueuePool
from sqlalchemy.sql import text

POOL_SIZE = 10
try:
    import uwsgi
    POOL_SIZE = int(uwsgi.opt['threads'])

    def postfork():
        engine.dispose()
    uwsgi.post_fork_hook = postfork
except ImportError:
    pass

DBURL = 'postgres://postgres:pass@127.0.0.1:5455/postgres'
engine = create_engine(DBURL, poolclass=QueuePool, pool_size=POOL_SIZE)

def db_conn(request):
    conn = engine.contextual_connect()
    def cleanup(request):
        conn.close()
    request.add_finished_callback(cleanup)
    return conn

def some_view(request):
    conn = request.db_conn
    with conn.begin() as trans:
        s = text('SELECT 1')
        cur = conn.execute(s)
        result = cur.first()
    return Response('<h1>{}</h1>'.format(result))

def main():
    config = Configurator()
    config.add_request_method(db_conn, reify=True)
    config.add_route('some_view', '/')
    config.add_view(some_view, route_name='some_view')
    app = config.make_wsgi_app()
    return app

application = main()

我正在使用uWSGI:

uwsgi --wsgi-file webapp.py  --http :9090 --master --processes 2 --threads 2

我的主要问题是该代码是否正确。我可以确定不同的进程/线程将使用不同的连接吗?

我有2个进程,每个进程有2个线程,我的假设是:

  • 在uWSGI post-fork挂钩中调用engine.dispose()可确保每个进程都有自己的连接

  • 调用config.add_request_method(db_conn, reify=True)会将SQLAlchemy连接对象添加到请求中。在引擎盖下,使用线程本地来确保线程之间的不同连接

  • 我正在联系调用contextual_connect()而不仅仅是connect(),但我认为使用哪种方法并不重要。

但我不确定它们是否正确,特别是第二种。

最后一句话,我了解SQLAlchemy的scoped_sessionsessionmaker,但我想直接使用连接对象来更好地理解它是如何工作的。

1 个答案:

答案 0 :(得分:2)

我没有看到您的示例代码有任何问题。我也同意,我认为你应该使用connect()代替contextual_connect()