性能优化 #
性能优化是生产环境应用的重要考量。本节将介绍Rocket应用的性能优化技巧。
异步优化 #
使用异步处理 #
rust
#[get("/users")]
async fn list_users(db: Db) -> Json<Vec<User>> {
let users = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(&mut **db)
.await
.unwrap_or_default();
Json(users)
}
并发处理 #
rust
use futures::future::join_all;
#[get("/dashboard")]
async fn dashboard(db: Db) -> Json<Dashboard> {
let users = sqlx::query_as!(User, "SELECT * FROM users LIMIT 10");
let posts = sqlx::query_as!(Post, "SELECT * FROM posts LIMIT 10");
let stats = sqlx::query_as!(Stats, "SELECT * FROM stats LIMIT 1");
let (users, posts, stats) = tokio::join!(
users.fetch_all(&mut **db),
posts.fetch_all(&mut **db),
stats.fetch_one(&mut **db)
);
Json(Dashboard {
users: users.unwrap_or_default(),
posts: posts.unwrap_or_default(),
stats: stats.ok(),
})
}
连接池优化 #
配置连接池 #
toml
[default.databases.my_db]
url = "postgres://user:password@localhost/mydb"
pool_size = 20
timeout = 5
连接池大小计算 #
text
pool_size = CPU核心数 * 2 + 有效磁盘数
缓存策略 #
内存缓存 #
rust
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use std::time::{Duration, Instant};
pub struct Cache {
data: Arc<RwLock<HashMap<String, CacheEntry>>>,
}
struct CacheEntry {
value: String,
expires_at: Instant,
}
impl Cache {
pub fn new() -> Self {
Self {
data: Arc::new(RwLock::new(HashMap::new())),
}
}
pub async fn get(&self, key: &str) -> Option<String> {
let data = self.data.read().await;
data.get(key)
.filter(|e| e.expires_at > Instant::now())
.map(|e| e.value.clone())
}
pub async fn set(&self, key: String, value: String, ttl: Duration) {
let mut data = self.data.write().await;
data.insert(key, CacheEntry {
value,
expires_at: Instant::now() + ttl,
});
}
}
使用缓存 #
rust
use std::time::Duration;
#[get("/users/<id>")]
async fn get_user_cached(
id: u32,
db: Db,
cache: &State<Cache>,
) -> Option<Json<User>> {
let cache_key = format!("user:{}", id);
if let Some(cached) = cache.get(&cache_key).await {
return Some(Json(serde_json::from_str(&cached).unwrap()));
}
let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
.fetch_optional(&mut **db)
.await
.ok()??;
cache.set(
cache_key,
serde_json::to_string(&user).unwrap(),
Duration::from_secs(300),
).await;
Some(Json(user))
}
响应压缩 #
启用压缩 #
rust
use rocket::fairing::{Fairing, Info, Kind};
use rocket::{Request, Response};
struct Compression;
#[rocket::async_trait]
impl Fairing for Compression {
fn info(&self) -> Info {
Info {
name: "Response Compression",
kind: Kind::Response,
}
}
async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
if let Some(accept) = request.headers().get_one("Accept-Encoding") {
if accept.contains("gzip") {
response.set_header(rocket::http::Header::new("Content-Encoding", "gzip"));
}
}
}
}
查询优化 #
分页查询 #
rust
#[get("/users?<page>&<per_page>")]
async fn list_users_paginated(
db: Db,
page: Option<i64>,
per_page: Option<i64>,
) -> Json<Vec<User>> {
let page = page.unwrap_or(1);
let per_page = per_page.unwrap_or(20).min(100);
let offset = (page - 1) * per_page;
let users = sqlx::query_as!(
User,
"SELECT * FROM users ORDER BY id LIMIT $1 OFFSET $2",
per_page,
offset
)
.fetch_all(&mut **db)
.await
.unwrap_or_default();
Json(users)
}
索引优化 #
sql
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_posts_user_id ON posts(user_id);
CREATE INDEX idx_posts_created_at ON posts(created_at DESC);
静态资源优化 #
缓存静态资源 #
rust
use rocket::fs::NamedFile;
use rocket::http::Header;
#[get("/static/<file..>")]
async fn static_files(file: std::path::PathBuf) -> Option<(NamedFile, Header<'static>)> {
let path = std::path::Path::new("static/").join(file);
let named_file = NamedFile::open(&path).await.ok()?;
let cache_header = Header::new("Cache-Control", "public, max-age=31536000");
Some((named_file, cache_header))
}
性能监控 #
请求计时 #
rust
use rocket::fairing::{Fairing, Info, Kind};
use rocket::{Request, Data, Response};
use std::time::Instant;
struct RequestTimer;
#[rocket::async_trait]
impl Fairing for RequestTimer {
fn info(&self) -> Info {
Info {
name: "Request Timer",
kind: Kind::Request | Kind::Response,
}
}
async fn on_request(&self, request: &mut Request<'_>, _data: &mut Data<'_>) {
request.local_cache(|| Instant::now());
}
async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
if let Some(start) = request.local_cache::<Instant>().get() {
let duration = start.elapsed();
response.set_header(rocket::http::Header::new(
"X-Response-Time",
format!("{:.2}ms", duration.as_secs_f64() * 1000.0)
));
}
}
}
性能检查清单 #
数据库 #
- [ ] 使用连接池
- [ ] 添加适当索引
- [ ] 使用分页查询
- [ ] 避免 N+1 查询
缓存 #
- [ ] 实现热点数据缓存
- [ ] 设置合理的过期时间
- [ ] 使用缓存预热
网络 #
- [ ] 启用响应压缩
- [ ] 设置静态资源缓存
- [ ] 减少请求大小
代码 #
- [ ] 使用异步处理
- [ ] 避免阻塞操作
- [ ] 优化热点代码
完整示例 #
rust
#[macro_use] extern crate rocket;
use rocket::serde::json::Json;
use rocket_db_pools::{Database, Connection, sqlx};
use sqlx::PgPool;
use std::time::{Duration, Instant};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(Database)]
#[database("postgres")]
struct Db(PgPool);
struct Cache {
data: Arc<RwLock<HashMap<String, (String, Instant)>>>,
}
impl Cache {
fn new() -> Self {
Self {
data: Arc::new(RwLock::new(HashMap::new())),
}
}
async fn get(&self, key: &str) -> Option<String> {
let data = self.data.read().await;
data.get(key)
.filter(|(_, exp)| exp > &Instant::now())
.map(|(v, _)| v.clone())
}
async fn set(&self, key: String, value: String, ttl: Duration) {
let mut data = self.data.write().await;
data.insert(key, (value, Instant::now() + ttl));
}
}
#[derive(sqlx::FromRow, rocket::serde::Serialize)]
struct User {
id: i32,
name: String,
}
#[get("/users/<id>")]
async fn get_user(id: i32, mut db: Connection<Db>, cache: &rocket::State<Cache>) -> Option<Json<User>> {
let cache_key = format!("user:{}", id);
if let Some(cached) = cache.get(&cache_key).await {
return Some(Json(serde_json::from_str(&cached).unwrap()));
}
let user = sqlx::query_as!(User, "SELECT id, name FROM users WHERE id = $1", id)
.fetch_optional(&mut **db)
.await
.ok()??;
cache.set(cache_key, serde_json::to_string(&user).unwrap(), Duration::from_secs(60)).await;
Some(Json(user))
}
#[launch]
fn rocket() -> _ {
rocket::build()
.attach(Db::init())
.manage(Cache::new())
.mount("/api", routes![get_user])
}
下一步 #
掌握了性能优化后,让我们继续学习 RESTful API,开始实战项目。
最后更新:2026-03-28