RustWeb服务部署与环境变量配置全解析
立即解锁
发布时间: 2025-09-04 01:54:29 阅读量: 262 订阅数: 45 AIGC 

### Rust Web 服务部署与环境变量配置全解析
在 Rust 开发中,完成业务逻辑编写后,将应用部署到生产环境是关键的下一步。本文将深入探讨 Rust 应用部署过程中的重要环节,包括环境变量的配置、二进制文件的优化以及跨平台编译等内容。
#### 1. 认证与授权相关未覆盖内容
在认证和授权方面,有一些内容未详细涉及。例如,设置会话数据库来存储令牌,以便在数据泄露或用户有其他需求时使令牌失效。可以通过设置 Redis 实例,在生成每个令牌时,不仅将结果返回给客户端,还将其存储在 Redis 键值存储中。
另外,重置用户密码和创建刷新令牌也是重要的话题。重置用户密码可以通过创建一个新的重置密码表,通过电子邮件向用户发送带有哈希值的链接,用户点击链接后,打开新的 REST 端点验证哈希值并更新密码。
使用 TLS 进行安全连接也是需要考虑的。在大型应用中,这通常由基础设施(如 NGINX 实例)处理。
#### 2. 认证与授权总结
每个 Web 服务都需要处理认证和授权,无论是在微服务架构中进行自我认证,还是在客户端/服务器模型中提供 API 时。存储用户密码时,要先对密码进行哈希和加盐处理,再存储到数据库中,并使用最新的哈希算法建议。
Web 应用通常提供一些无需用户认证即可访问的端点,注册端点用于向服务器发送电子邮件和密码组合。根据应用的复杂性,可以仅存储电子邮件和密码,也可以为账户添加用户角色和其他属性。确保为表中的每个条目添加 ID,以便将资源与相应的账户关联起来。
登录端点是应用的入口,它会返回一个令牌,用于授权未来的 HTTP 请求。中间件位于传入的 HTTP 调用和路由处理程序之间,用于检查有效令牌并从中提取信息。令牌是一种无状态的认证方式,也可以选择使用数据库表存储所有活动令牌,以便在未来使令牌失效。中间件会向路由处理程序添加一个新参数(账户 ID),由它们来检查客户端是否有权修改底层资源。可以通过应用代码或基础设施设置来建立安全连接(如 TLS)。
#### 3. 应用部署概述
应用部署涉及多个方面,包括设置应用以读取环境变量、优化构建的二进制文件以用于生产、将服务跨平台编译到不同的操作系统、创建更复杂的构建过程、创建优化的 Docker 文件以及使用 Docker Compose 设置本地 Docker 环境。
在将代码从本地机器迁移到第三方托管提供商时,需要提取硬编码的参数,并通过环境变量或 CLI 命令提供这些参数。第三方提供商会注入 IP 地址、端口和数据库 URL 等设置,Rust 提供了多种解析环境变量或 CLI 命令的方法。
#### 4. 通过环境变量设置应用
当将 Web 服务编译为二进制文件后,需要使其能够适应不同的环境。通常有三种方式向应用提供输入:通过配置文件、通过命令行输入和通过 `.env` 文件。
| 输入方式 | 优点 | 缺点 |
| ---- | ---- | ---- |
| 配置文件 | 无需记住所有 CLI 命令,可通过查看 JSON 或 TOML 文件了解服务器启动方式 | API 密钥和机密信息不宜提交到仓库,生产环境需要其他方式传递 |
| 命令行输入 | 在不同环境中使用不同的 CLI 输入,无需维护多个配置文件 | 仅从代码中难以了解传递给应用的参数 |
| `.env` 文件 | 可本地保存,存储 API 密钥和其他机密信息,生产环境可使用不同的 `.env` 文件提供正确的机密信息 | 难以猜测可能的命令类型 |
##### 4.1 设置配置文件
使用 `config-rs` 第三方 crate 来解析配置文件和读取配置。首先,在 `Cargo.toml` 中添加该 crate:
```toml
[package]
name = "rust-web-dev"
version = "1.0.0"
authors = ["Bastian Gruber <[email protected]>"]
edition = "2018"
[dependencies]
warp = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.1.1", features = ["full"] }
handle-errors = { path = "handle-errors", version = "0.1.0" }
tracing = { version = "0.1", features = ["log"] }
tracing-subscriber = "0.2"
sqlx = { version = "0.5", features = [ "runtime-tokio-rustls", "migrate", "postgres" ] }
reqwest = { version = "0.11", features = ["json"] }
reqwest-middleware = "0.1.1"
reqwest-retry = "0.1.1"
rand = "0.8"
rust-argon2 = "1.0"
paseto = "2.0"
config = { version = "0.13.1", features = ["toml"] }
```
然后,在项目根文件夹中创建 `setup.toml` 文件,存储可能会变化的参数:
```toml
log_level = "warn"
database_host = "localhost"
database_port = 5432
database_name = "rustwebdev"
port = 8080
```
在 `main.rs` 中读取这些参数:
```rust
#![warn(clippy::all)]
use config::Config;
use handle_errors::return_error;
use tracing_subscriber::fmt::format::FmtSpan;
use warp::{http::Method, Filter};
use std::env;
mod profanity;
mod routes;
mod store;
mod types;
#[derive(Parser, Debug, Default, serde::Deserialize, PartialEq)]
struct Args {
log_level: String,
/// URL for the postgres database
database_host: String,
/// PORT number for the database connection
database_port: u16,
/// Database name
database_name: String,
/// Web server port
port: u16,
}
#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
let config = Config::builder()
.add_source(config::File::with_name("setup"))
.build()
.unwrap();
let config = config
.try_deserialize::<Args>()
.unwrap();
let log_filter = std::env::var("RUST_LOG").unwrap_or_else(|_| {
format!(
"handle_errors={},rust_web_dev={},warp={}",
config.log_level, config.log_level, config.log_level
)
});
let store = store::Store::new(&format!(
"postgres://{}:{}/{}",
config.database_host, config.database_port, config.database_name
))
.await?;
sqlx::migrate!().run(&store.clone().connection).await?;
let store_filter = warp::any().map(move || store.clone());
warp::serve(routes).run(([127, 0, 0, 1], config.port)).await;
Ok(())
}
```
通过这种方式,实现了参数与源代码的解耦,修改数据库名称、端口号或数据库主机时,无需修改代码,避免引入意外的错误。
##### 4.2 接受命令行输入
如果不需要复杂的配置文件,或者部署环境使用 CLI 命令提供参数,可以使用 Rust 标准库的 `std::env::args` 方法读取命令行参数,也可以使用 `clap` crate 更方便地处理。
首先,在 `Cargo.toml` 中添加 `clap` crate:
```toml
[package]
name = "rust-web-dev"
version = "1.0.0"
authors = ["Bastian Gruber <[email protected]>"]
edition = "2018"
[dependencies]
warp = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde
```
0
0
复制全文
相关推荐









