跳转到主要内容

无显式锁的,可选暴增的高吞吐量池

项目描述

asyncio-connection-pool

GitHub Workflow Status (main) PyPI PyPI - Python Version codecov License Fellow Careers

这是一个通用的、高吞吐量、可选暴增的asyncio池。

一些酷炫的功能

  • 无锁[^1]; 不需要获取 asyncio.Lockasyncio.Condition 就可以获得连接。
  • 在无需让出事件循环的情况下检索可用连接。
  • 当指定了 burst_limit 时,max_size 起到一个“软”限制的作用;池可以超过这个限制来处理增加的负载,之后会缩小回来。
  • 池的内容可以是任何东西;只需实现一个 ConnectionStrategy

[^1]: 从理论上讲,在asyncio任务执行期间,存在一个隐式的“锁”。除非当前任务让出(因为它是协作式多任务),否则其他任务不能执行,因此在那个时间段内的任何操作都是原子的。

为什么?

我们之前使用不同的池来处理Redis连接,并注意到在重负载下,我们会花费很多时间等待锁,即使池中还有可用的连接。

我们还认为,如果不需要一直保持很多连接打开,但在需要时仍然能够创建更多连接,那会很好。

API

asyncio_connection_pool.ConnectionPool

这是池的实现。它是一个通用的连接类型,所有实现特定的逻辑都包含在一个 ConnectionStrategy 中。

创建连接池的步骤如下

from asyncio_connection_pool import ConnectionPool

pool = ConnectionPool(strategy=my_strategy, max_size=15)

构造函数可以可选地传入一个整数作为 burst_limit。这允许连接池在临时情况下打开比 max_size 更多的连接。

@asynccontextmanager async def get_connection(self) -> AsyncIterator[Conn]

此方法是获取连接池中连接的唯一方式。它通常如下使用

pool = ConnectionPool(...)

async with pool.get_connection() as conn:
    # Use the connection
    pass

当进入 async with 块时,会检索一个连接。如果需要打开连接或连接池已满且没有可用连接,调用者将交出事件循环。

当退出块时,连接将返回到连接池。

asyncio_connection_pool.ConnectionStrategy

这是一个抽象类,它定义了作为 strategy 传入的对象的接口。一个子类 必须 实现以下方法

async def create_connection(self) -> Awaitable[Conn]

当请求连接且所有连接都在使用时,此方法被调用以创建到资源的新的连接。只要连接池未满,就会发生这种情况。

此方法的调用结果将提供给连接池的消费者,并在大多数情况下将存储在池中以供以后重用。

如果此方法抛出异常,它将冒泡到调用 ConnectionPool.get_connection() 的框架。

def connection_is_closed(self, conn: Conn) -> bool

此方法用于检查连接是否不能再使用。当连接池检索连接以提供给客户端时,此方法被调用以确保其有效性。

如果连接无效,则返回值应为 True

如果此方法抛出异常,则假定连接无效。传入的连接将被丢弃并检索新的连接。除非异常不是 BaseException,如 asyncio.CancelledError,否则会抑制异常。避免在这种情况下泄露连接是 ConnectionStrategy 实现的责任。

async def close_connection(self, conn: Conn)

当连接池超出 max_size(即正在膨胀)且返回不再需要的连接(即没有更多消费者等待连接)时,此方法被调用以关闭连接。

如果此方法抛出异常,则假定连接已关闭,异常将冒泡到 ConnectionPool.get_connection().__aexit__ 的调用者(通常是 async with 块)。

与第三方库的集成

此软件包包括对 ddtrace/datadogaioredis (<2.0.0) 的支持。

asyncio_connection_pool.contrib.datadog.ConnectionPool

此类继承了包根目录中的 ConnectionPool,并添加了大量跟踪、仪表和事件。构造函数除了基类的参数外,还支持

  • 必需的 service_name 参数:所有指标的前缀
  • 可选的 extra_tags 参数:提供给所有指标的其他标签(格式为 "key:value" 的字符串)

asyncio_connection_pool.contrib.aioredis.RedisConnectionStrategy

此类实现了 ConnectionStrategy 抽象方法,使用 aioredis.Redis 对象作为连接。构造函数接受任意参数并将它们转发给 aioredis.create_redis

没有锁,这如何保证安全?

我鼓励您阅读源代码以了解情况(它注释得相当好)。如果您发现任何逻辑错误,请随时提交问题。

项目详情


下载文件

下载您平台对应的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分发

asyncio_connection_pool-1.0.0.tar.gz (13.5 kB 查看哈希值)

上传时间

构建分发

asyncio_connection_pool-1.0.0-py3-none-any.whl (9.3 kB 查看哈希值)

上传时间 Python 3

由以下机构支持