如何根据请求创建SQLAlchemy数据库会话

时间:2019-01-10 09:28:46

标签: python python-3.x sqlalchemy multi-tenant falconframework

我有一个多租户python falcon应用程序。每个租户都有自己的数据库。在收到请求时,我需要连接到租户数据库。

但是这里有一种情况。数据库配置存储在另一个服务上,并且配置会定期更改。

我在进程资源之前尝试了会话创建。但是此更改后,sql查询速度变慢。为了加快速度,我该怎么办? 附言:我使用PostgreSQL

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
import config
import json
import requests
class DatabaseMiddleware:
    def __init__(self):
        pass
    def process_resource(self, req, resp, resource, params):
        engineConfig = requests.get('http://database:10003/v1/databases?loadOnly=config&appId=06535108-111a-11e9-ab14-d663bd873d93').text
        engineConfig = json.loads(engineConfig)
        engine = create_engine(
            '{dms}://{user}:{password}@{host}:{port}/{dbName}'.format(
            dms= engineConfig[0]['config']['dms'],
            user= engineConfig[0]['config']['user'],
            password= engineConfig[0]['config']['password'],
            host= engineConfig[0]['config']['host'],
            port= engineConfig[0]['config']['port'],
            dbName= engineConfig[0]['config']['dbName']
        ))
        session_factory = sessionmaker(bind=engine,autoflush=True)
        databaseSession = scoped_session(session_factory)
        resource.databaseSession = databaseSession
    def process_response(self, req, resp, resource, req_succeeded):
        if hasattr(resource, 'mainDatabase'):
            if not req_succeeded:
                resource.databaseSession.rollback()
            self.databaseSession.remove()

2 个答案:

答案 0 :(得分:0)

您的方法可能是错误的,因为它违反了engine disposal中描述的引擎实例的预期使用模式。引擎实例的生存期应与中间件实例的生存期相同。

  

引擎指的是一个连接池,这意味着在正常情况下,当引擎对象仍驻留在内存中时,存在打开的数据库连接。当引擎被垃圾回收时,该引擎将不再引用其连接池,并且假设仍然没有检出其连接,则该池及其连接也将被垃圾回收,从而具有关闭实际连接的作用。数据库连接。但是否则,如果引擎使用QueuePool的通常默认池实现,则引擎将保留开放的数据库连接。

     

引擎通常是永久性的固定装置,可以在应用程序的整个生命周期内预先建立并维护。它不打算在每个连接的基础上创建和处置。相反,它是一个注册表,它维护连接池以及有关正在使用的数据库和DBAPI的配置信息,以及每个数据库资源的某种程度的内部缓存。

答案 1 :(得分:0)

我将SQLService与SQLAlchemy结合使用,作为SQLAlchemy会话管理器和ORM层的接口层,很好地集中了SQLAlchemy的核心功能。

这是我的中间件组件定义:

class DatabaseSessionComponent(object):
    """ Initiates a new Session for incoming request and closes it in the end. """

    def __init__(self, sqlalchemy_database_uri):
        self.sqlalchemy_database_uri = sqlalchemy_database_uri

    def process_resource(self, req, resp, resource, params):
        resource.db = sqlservice.SQLClient(
            {
                "SQL_DATABASE_URI": self.sqlalchemy_database_uri,
                "SQL_ISOLATION_LEVEL": "SERIALIZABLE",
                "SQL_ECHO": False,
                "SQL_ECHO_POOL": False,
                "SQL_CONVERT_UNICODE": True,
                "SQL_POOL_RECYCLE": 3600,
                "SQL_AUTOCOMMIT": False,
                "SQL_AUTOFLUSH": True,
                "SQL_EXPIRE_ON_COMMIT": True,
            },
            model_class=BaseModel,
        )

    def process_response(self, req, resp, resource):
        if hasattr(resource, "db"):
            resource.db.disconnect()

在API的实例中包含其实例:

api = falcon.API(
    middleware=[
        DatabaseSessionComponent(os.environ["SQLALCHEMY_DATABASE_URI"]),
    ]
)