29 个发布版本
0.12.1 | 2024 年 5 月 7 日 |
---|---|
0.11.2 | 2024 年 4 月 10 日 |
0.11.0 | 2024 年 3 月 31 日 |
0.10.0 | 2023 年 9 月 25 日 |
0.2.0 | 2019 年 11 月 14 日 |
#6 in 数据库接口
1,068,152 每月下载次数
用于 494 个 Crates (75 直接)
80KB
1.5K SLoC
Deadpool
Deadpool 是一个简单的异步池,用于任何类型的连接和对象。
此 crate 提供了两种实现
-
管理池 (
deadpool::managed::Pool
)- 按需创建和回收对象
- 适用于 数据库连接池
- 通过您的
Cargo.toml
中的managed
功能启用
-
未管理池 (
deadpool::unmanaged::Pool
)- 所有对象都需要由用户创建并手动添加到池中。也可以从现有对象集合创建池。
- 通过您的
Cargo.toml
中的unmanaged
功能启用
功能
功能 | 描述 | 额外依赖 | 默认 |
---|---|---|---|
managed |
启用管理池实现 | - | 是 |
unmanaged |
启用未管理池实现 | - | 是 |
rt_tokio_1 |
启用对 tokio crate 的支持 | tokio/时间 |
否 |
rt_async-std_1 |
启用对 async-std crate 的支持 | async-std |
否 |
序列化 |
启用对池配置反序列化的支持 | 序列化/derive |
否 |
运行时功能(rt_*
)仅在需要超时支持时才需要。如果在创建池时没有指定运行时,尝试使用超时,池的获取方法将返回一个 PoolError::NoRuntimeSpecified
错误。
托管池(又称连接池)
这是任何类型连接池的明显选择。Deadpool 已经内置了一些 数据库连接池,可以直接使用。
示例
use deadpool::managed;
#[derive(Debug)]
enum Error { Fail }
struct Computer {}
impl Computer {
async fn get_answer(&self) -> i32 {
42
}
}
struct Manager {}
impl managed::Manager for Manager {
type Type = Computer;
type Error = Error;
async fn create(&self) -> Result<Computer, Error> {
Ok(Computer {})
}
async fn recycle(&self, _: &mut Computer, _: &managed::Metrics) -> managed::RecycleResult<Error> {
Ok(())
}
}
type Pool = managed::Pool<Manager>;
#[tokio::main]
async fn main() {
let mgr = Manager {};
let pool = Pool::builder(mgr).build().unwrap();
let mut conn = pool.get().await.unwrap();
let answer = conn.get_answer().await;
assert_eq!(answer, 42);
}
数据库连接池
Deadpool 通过实现 deadpool::managed::Manager
特性来支持各种数据库后端。以下后端目前受支持
再次使用连接池的原因
Deadpool 绝非唯一可用的池实现。它做得略有不同,这就是它存在的主要原因。
-
Deadpool 与任何执行器兼容。 使用
Drop
特性将对象返回到池中。这些对象的健康状态在下次检索时检查,而不是在它们返回时检查。Deadpool 从不执行任何后台操作。这就是为什么 Deadpool 不需要生成 futures,也不依赖于任何类型的后台线程或任务。 -
相同的启动和运行时行为。当编写长时间运行的应用程序时,如果数据库连接暂时不可用,通常在启动和运行时之间不应有任何差异。没有人会期望应用程序在运行时数据库不可用时崩溃。因此,在启动时也不应崩溃。创建池永远不会失败,错误仅在调用
Pool::get()
时返回。如果您真的想在启动时如果对象无法创建而导致应用程序崩溃,请直接在创建池后调用
pool.get().await.expect("DB connection failed")
。 -
Deadpool 很快。 在处理锁定原语时,它们被保持尽可能短的时间。当将对象返回到池中时,仅锁定一个互斥锁,当从池中检索对象时,使用信号量来尽可能减少互斥锁的竞争。
-
Deadpool 很简单。 简单到极点。API 表面很小。实际代码仅约 100 行代码,位于两个函数
Pool::get
和Object::drop
中。 -
Deadpool 可扩展。 通过使用
post_create
、pre_recycle
和post_recycle
钩子,您可以自定义对象创建和回收以满足您的需求。 -
Deadpool 提供了见解。 所有对象都跟踪
Metrics
,池提供了一个status
方法,可用于了解其内部工作细节。 -
Deadpool 可调整大小。您可以在运行时调整池的大小,而无需重新启动应用程序。
非托管池
当您无法编写要池化的对象的经理,或者根本不想编写时,非托管池非常有用。此池实现比托管池稍快,因为它不使用 Manager
特性来 创建
和 回收
对象,而是将其留给用户。
非托管池示例
use deadpool::unmanaged::Pool;
struct Computer {}
impl Computer {
async fn get_answer(&self) -> i32 {
42
}
}
#[tokio::main]
async fn main() {
let pool = Pool::from(vec![
Computer {},
Computer {},
]);
let s = pool.get().await.unwrap();
assert_eq!(s.get_answer().await, 42);
}
常见问题解答
为什么 Deadpool 依赖于 tokio
?我以为它是运行时无关的...
Deadpool 依赖于 tokio::sync::Semaphore
。这 并不 意味着正在使用 tokio 运行时或其他 tokio 的一部分,或者它们将成为您的构建的一部分。您可以通过在自己的代码库中运行以下命令轻松检查此问题
cargo tree --format "{p} {f}"
许可证
根据您的选择,许可方式为:
- Apache License,版本 2.0 (LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
。
依赖关系
~2–12MB
~138K SLoC