【问题标题】:SQLAlchemy and Google Cloud Sql session poolSQLAlchemy 和 Google Cloud Sql 会话池
【发布时间】:2022-11-01 13:27:22
【问题描述】:

我正在使用 graphql(草莓)创建一个异步 fastAPI 微服务。我的数据库托管在 GoogleCloudSQL 上,它是一个 postgres 数据库。我的微服务在本地和本地数据库上运行得非常好,但是现在当我将我的连接器构建到 GoogleCloudSQL 时,它不再那么好用了。 我的问题是,如何为我的每个请求创建一个会话池并生成会话?

以下是一些代码sn-ps:

`
# [START cloud_sql_postgres_sqlalchemy_connect_connector]
import os
from sqlalchemy.ext.asyncio import create_async_engine, AsyncEngine
from google.cloud.sql.connector import IPTypes, create_async_connector
import asyncpg


async def connect_with_connector() -> AsyncEngine:
    instance_connection_name = os.environ["INSTANCE_CONNECTION_NAME"]  # e.g.         'project:region:instance'
    db_user = os.environ["DB_USER"]  # e.g. 'my-db-user'
    db_pass = os.environ["DB_PASS"]  # e.g. 'my-db-password'
    db_name = os.environ["DB_NAME"]  # e.g. 'my-database'

    ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC

    # initialize Cloud SQL Python Connector object
    connector = await create_async_connector()

    async def getconn() -> asyncpg.Connection:
        conn: asyncpg.Connection = await connector.connect_async(
            instance_connection_name,
            "asyncpg",
            user=db_user,
            password=db_pass,
            db=db_name,
            ip_type=IPTypes.PUBLIC
        )

        return conn

    # The Cloud SQL Python Connector can be used with SQLAlchemy
    # using the 'creator' argument to 'create_engine'

    connection = await getconn()

    pool = create_async_engine(
        "postgresql+asyncpg://",
        creator=connection,
        # [START_EXCLUDE]
        # Pool size is the maximum number of permanent connections to keep.
        pool_size=5,

        # Temporarily exceeds the set pool_size if no connections are available.
        max_overflow=2,

        # The total number of concurrent connections for your application will be
        # a total of pool_size and max_overflow.

        # 'pool_timeout' is the maximum number of seconds to wait when retrieving a
        # new connection from the pool. After the specified amount of time, an
        # exception will be thrown.
        pool_timeout=30,  # 30 seconds

        # 'pool_recycle' is the maximum number of seconds a connection can persist.
        # Connections that live longer than the specified amount of time will be
        # re-established
        pool_recycle=1800,  # 30 minutes
        # [END_EXCLUDE]
    )
    return pool`

这是我的会话生成器

    `@asynccontextmanager
    async def get_session() -> AsyncSession:
        engine = await connect_with_connector()
        async_session = sessionmaker(
        engine, class_=AsyncSession, expire_on_commit=False
        )
        async with async_session() as session:
            yield session`

当我尝试像这样执行我的查询时:

async with get_session() as session:
    selected = await session.execute(selectable)

我收到此错误: “‘连接’对象不可调用”

即使我在调试时看到 session 的类型为 AsyncSession

【问题讨论】:

  • “它不再那么好用了” - 你能更详细地解释一下吗?
  • 当我尝试执行查询时收到此错误selected = await db.execute(selectable)“'Connection' 对象不可调用”即使在调试时我看到会话的类型为 AsyncSession
  • 您能否分享完整的回溯,而不仅仅是错误消息。除非我们知道错误发生在哪里,否则“'Connection' 对象不可调用”并没有多大意义。

标签: python postgresql google-cloud-platform sqlalchemy google-cloud-sql


【解决方案1】:

错误的完整追溯

Connection' object is not callable
GraphQL request:2:5
1 | {
2 |     companies(first:10){
  |     ^
3 |         edges{
Traceback (most recent call last):
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/graphql/execution/execute.py", line 528, in await_result
    return_type, field_nodes, info, path, await result
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/strawberry/schema/schema_converter.py", line 513, in _async_resolver
    return await await_maybe(_get_result(_source, strawberry_info, **kwargs))
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/strawberry/utils/await_maybe.py", line 12, in await_maybe
    return await value
  File "/Users/sebigiurca/workspace/fastlead-backend/src/api/graphql/company/schema.py", line 39, in companies
    result = await session.execute(query)
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/ext/asyncio/session.py", line 215, in execute
    result = await greenlet_spawn(
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 115, in greenlet_spawn
    result = context.switch(*args, **kwargs)
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1711, in execute
    conn = self._connection_for_bind(bind)
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1552, in _connection_for_bind
    return self._transaction._connection_for_bind(
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 747, in _connection_for_bind
    conn = bind.connect()
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/future/engine.py", line 406, in connect
    return super(Engine, self).connect()
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 3315, in connect
    return self._connection_cls(self, close_with_result=close_with_result)
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 96, in __init__
    else engine.raw_connection()
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 3394, in raw_connection
    return self._wrap_pool_connect(self.pool.connect, _connection)
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 3361, in _wrap_pool_connect
    return fn()
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 320, in connect
    return _ConnectionFairy._checkout(self)
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 884, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 486, in checkout
    rec = pool._do_get()
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/pool/impl.py", line 146, in _do_get
    self._dec_overflow()
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 208, in raise_
    raise exception
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/pool/impl.py", line 143, in _do_get
    return self._create_connection()
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 266, in _create_connection
    return _ConnectionRecord(self)
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 381, in __init__
    self.__connect()
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 678, in __connect
    pool.logger.debug("Error on connect(): %s", e)
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 208, in raise_
    raise exception
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 673, in __connect
    self.dbapi_connection = connection = pool._invoke_creator(self)
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 230, in <lambda>
    return lambda crec: creator()
TypeError: 'Connection' object is not callable
Stack (most recent call last):
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/strawberry/fastapi/router.py", line 291, in execute
    return await self.schema.execute(
  File "/Users/sebigiurca/opt/miniconda3/envs/fastlead-conda/lib/python3.9/site-packages/strawberry/schema/schema.py", line 216, in execute
    self.process_errors(result.errors, execution_context=execution_context)C

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-13
    • 2020-12-07
    • 2018-02-08
    • 2016-06-06
    • 1970-01-01
    • 2018-11-21
    • 2019-03-26
    相关资源
    最近更新 更多