首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用r2d2在锈蚀/柴油应用程序中实现连接池

用r2d2在锈蚀/柴油应用程序中实现连接池
EN

Stack Overflow用户
提问于 2021-08-03 09:28:44
回答 2查看 2.1K关注 0票数 4

我正在尝试在一个生锈/柴油/火箭应用程序中实现连接池。我不知道如何确保只调用一次establish_pooled_connection()方法的内容,以便准备连接池。

这是我的密码。

来自lib.rs

代码语言:javascript
运行
复制
pub fn establish_pooled_connection() -> PooledConnection<ConnectionManager<PgConnection>> {
    dotenv().ok();

    let database_url = env::var("DB_URL")
        .expect("DATABASE_URL must be set");

    let manager = ConnectionManager::<PgConnection>::new(&database_url);
    let pool = r2d2::Pool::builder().build(manager).expect("Failed to create pool.");
    let conn = pool.clone().get().unwrap();
    return conn;
}

在这里,我在main.rs中使用了上述方法

代码语言:javascript
运行
复制
#[get("/", format = "json")]
fn find_all() -> Json<Vec<Person>> {
    let connection = establish_pooled_connection();

    let all: QueryResult<Vec<Person>> = person::table().get_results(&connection);
    ...

这里的问题是,每个get方法(例如,上面)都调用establish_pooled_connection(),并且所有东西都被重新实例化.

我来自java世界,依赖注入允许我们避免重新实例化。

在生锈/柴油应用程序中实现连接池的正确方法是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-08-03 10:02:07

您不会在每个处理程序中创建一个新的连接,而是使用框架的一些状态共享机制。

有关如何在火箭中使用状态的指南,请参阅这里,这将是一个很好的起点。

票数 2
EN

Stack Overflow用户

发布于 2022-09-10 08:44:44

这里的问题是,每个get方法(例如,上面)都调用establish_pooled_connection(),并且所有东西都被重新实例化.

我在建立池连接方面也遇到了困难,所以我想我应该把我所做的抛在脑后。

我是怎么解决的

我设法使用火箭/柴油应用程序中的池连接,将已建立的池添加到服务器状态,并通过该服务器状态从各个函数访问数据库。

代码语言:javascript
运行
复制
// add the `r2d2` feature for diesel 
use diesel::{
    r2d2::{ConnectionManager, Pool, PooledConnection},
    MysqlConnection,
};

// set an alias, so we don't have to keep writing out this long type
pub type DbPool = Pool<ConnectionManager<MysqlConnection>>;

// a real-world app would have more fields in the server state like 
// CORS options, environment values needed for external APIs, etc.
pub struct ServerState {
  pub db_pool: DbPool
}

火箭允许我们在用.manage()构建服务器时使用build()调用定义服务器状态。

代码语言:javascript
运行
复制
#[rocket::main]
pub async fn main() {
  let db_pool: DbPool = establish_connection_pool();

  rocket::build()
    .mount("/", routes![test]) // mount routes
    .manage(ServerState { db_pool })
    .launch()
    .await
    .expect("Failed to launch rocket server.")
}

因为Rocket允许我们从函数中检索服务器的状态,只要它们有Rocket的宏(getpost等),我们就可以从服务器状态检索数据库。

代码语言:javascript
运行
复制
use rocket::{get, serde::json::Json, State};

#[get("/test?<user_id>")]
pub async fn test(
  state: &State<ServerState>,
  user_id: String
) -> Result<Json<User>, Error> {
  let pooled = &state.db_pool.get()?;

  pooled.transaction(|| {
    // some diesel query
  })
}

我在这方面使用的版本如下所示。

代码语言:javascript
运行
复制
diesel = { version = "1.4.8", features = ["r2d2", "mysql", "chrono"] }
rocket = { version = "0.5.0-rc.1", features = ["json"] }

还有什么要考虑的

正如我前面所做的,有些人希望直接使用r2d2来设置池连接,这是有原因的。我个人认为,能够作为服务器状态中的字段传递到池中,将允许更好地控制编写集成测试。但是,您可能需要了解处理池连接的其他方法。

火箭提供了自己的解决方案,用rocket_sync_db_pools1和rocket_db_pools2处理池数据库连接。如果您在库中涵盖的数据库中使用diesel3和sqlx4之类的ORM,那么我强烈建议查看它们。

只需在项目的根目录中设置一个Rocket.toml文件,如下所示。

代码语言:javascript
运行
复制
[global.databases]
test_db = { url = "mysql://mysql:password@localhost:5432/test_db_name" }

现在,通过利用database宏的强大功能,您可以轻松地建立连接。

代码语言:javascript
运行
复制
#[macro_use]
extern crate rocket_sync_db_pools;

// as long as we set the `Rocket.toml` to include information about 
// what database we want to point to, the `database` macro does 
// the magic for us
#[database("test_db")]
pub struct TestDbConn(diesel::MysqlConnection);

// We can directly access the pooled connection as we did with the server state
#[get("/test?<user_id>")]
pub async fn test(
  conn: TestDbConn,
  user_id: String
) -> Result<Json<User>, Error> {
  conn.run(move || {
    // some diesel query
  })
}

1将rocket_sync_db_poolsdiesel这样的同步ORM结合使用。池/index.html#

2将rocket_db_pools与异步ORM(如deadpool-postgressqlx )结合使用。池/index.html#

3.

4.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68633531

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档