八、Rust 集成 Sqlx
Rust 语言级异步,是 xxx 版添加进来的特性。如果只是需要一款支持异步的连接池工具,推荐 tokio-postgres、deadpool-postgres。而用于生产工序,还是需要 ORM 的加入。本节我们来学习一下 sqlx。
本节需要 PostgreSQL 数据库,需要读者提前准备,并假定实例中已包含名为 postgres 的库,且账号为:postgres:postgres。
.
├── Cargo.lock
├── Cargo.toml
├── README.md
├── config.yaml
└── src
├── boot
│ ├── db.rs
│ └── mod.rs
├── main.rs
└── module
├── mod.rs
└── user
├── api.rs
├── mod.rs
└── model.rs
serde_yaml = "0.8.13"
sqlx = {version = "0.4.0-beta.1", default-features = false, features = ["runtime-tokio", "postgres", "macros", "chrono"]}
once_cell = "1.3.1"
chrono = { version = "0.4.15",features = ["serde"] }
server:
port: 8080
log: data/logs/app/web.log
env: dev
postgres:
dsn: postgres://postgres:postgres@192.168.24.251:5432/postgres
min: 5
max: 15
use std::sync::Arc;
use once_cell::sync::OnceCell;
use serde::Deserialize;
use crate::boot;
pub mod db;
#[derive(Debug, Deserialize)]
pub struct Conf {
pub server: Server,
pub postgres: Option<Postgres>,
}
#[derive(Debug, Deserialize)]
pub struct Server {
pub port: u32,
pub log: String,
pub env: String,
}
#[derive(Debug, Deserialize)]
pub struct Postgres {
pub dsn: String,
pub min: u32,
pub max: u32,
}
#[allow(dead_code)]
pub fn global() -> &'static Arc<Conf> {
static CONFIG: OnceCell<Arc<Conf>> = OnceCell::new();
CONFIG.get_or_init(|| {
let s = std::fs::read_to_string(&"config.yaml").unwrap();
Arc::new(serde_yaml::from_str(&s).unwrap())
})
}
pub fn start() {
boot::db::init_db_pool()
}
impl Conf {
#[allow(dead_code)]
pub fn get_env(&self) -> String {
self.server.env.clone()
}
#[allow(dead_code)]
pub fn addr(&self) -> String {
format!("0.0.0.0:{}", self.server.port)
}
}
use once_cell::sync::OnceCell;
use sqlx::{Pool, Postgres};
use sqlx::postgres::PgPoolOptions;
pub static POSTGRES_POOL: OnceCell<Pool<Postgres>> = OnceCell::new();
pub fn init_db_pool() {
if let Some(pg) = &crate::boot::global().postgres {
let pool = PgPoolOptions::new()
.min_connections(pg.min)
.max_connections(pg.max)
.connect_lazy(&pg.dsn).unwrap();
assert!(POSTGRES_POOL.set(pool).is_ok());
println!("datasource: {}\n min: {}\n max: {}", pg.dsn, pg.min, pg.max)
}
}
#[allow(dead_code)]
pub fn get_pool() -> Option<&'static Pool<Postgres>> {
POSTGRES_POOL.get()
}
#[macro_use]
extern crate validator_derive;
use actix_web::{App, HttpServer};
mod boot; // 增加了这里
mod module;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
boot::start(); // 增加了这里
HttpServer::new(move || App::new()
.service(module::handler::api_routes())
).bind(boot::global().addr())?.run().await
}
至此,便使我们的项目集成了 Sqlx,这款 Rust 异步 ORM 框架。现在,可以尝试编译,和启动我们的服务。
$ cargo run
Compiling rust-demo v0.1.0 (~/Rust-Study/rust-demo)
Finished dev [unoptimized + debuginfo] target(s) in 6.52s
Running `target/debug/rust-demo`
datasource: postgres://postgres:postgres@192.168.24.251:5432/postgres
min: 5
max: 15
或
$ ./target/debug/rust-demo
datasource: postgres://postgres:postgres@192.168.24.251:5432/postgres
min: 5
max: 15
为使每一小节,都尽可能简单/轻巧,本节就先这样。下一节,我们具体来看,使用 Sqlx 访问数据库 !~