使用 Actix-Web、SQLx 和 Redis 构建高性能 Rust Web 服务

使用 Actix-Web、SQLx 和 Redis 构建高性能 Rust Web 服务

在本教程中,我们将详细介绍如何在 Windows 系统上使用 Actix-Web 框架、SQLx 数据库工具和 Redis 缓存来构建一个高性能的 Rust Web 服务。我们将创建一个用户管理系统,包括获取单个用户、创建用户和获取所有用户的功能。

什么是 Actix-Web

Actix-Web 是一个用于构建 Web 应用程序的高性能、异步框架,基于 Rust 语言。它具有以下特点:

  • 异步 :使用 tokioasync-std 等异步运行时,提供高性能和高并发处理能力。
  • 中间件:支持中间件机制,可以方便地扩展功能。
  • 路由:灵活的路由机制,支持路径参数、查询参数等多种路由方式。
  • 类型安全:利用 Rust 的类型系统,确保代码的类型安全性和健壮性。
  • 社区支持:拥有活跃的开发者社区和丰富的文档资源。

准备工作

安装 Rust 和 Cargo

首先,确保你已经安装了 Rust 编程语言和 Cargo 包管理器。你可以在 Rust 官网 上找到适用于 Windows 的安装指南。按照提示运行 Rust 安装程序,并在安装过程中选择安装 Visual C++ 构建工具。

安装 MySQL

安装 MySQL 数据库,并设置好对应的环境变量。你可以从 MySQL 官网 下载适用于 Windows 的安装程序,并按照官方指南进行安装。

安装 Redis

安装 Redis,并设置好对应的环境变量。你可以从 Redis 官网 下载 Windows 版本的安装程序,并按照官方指南进行安装。

创建项目

首先,使用 Cargo 创建一个新的 Rust 项目:

sh 复制代码
cargo new my_actix_app
cd my_actix_app

添加依赖项

编辑 Cargo.toml 文件,添加所需的依赖项:

toml 复制代码
[package]
name = "my_actix_app"
version = "0.1.0"
edition = "2021"

[dependencies]
actix-web = "4.0"
sqlx = { version = "0.5", features = ["mysql", "runtime-tokio-native-tls"] }
redis = "0.26"
dotenv = "0.15"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

创建数据库表

在 MySQL 数据库中创建一个名为 users 的表,包括 idnameemail 字段。你可以使用以下 SQL 语句来创建表:

sql 复制代码
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL
);

编写代码

src/main.rs 文件中编写代码。以下是完整的代码示例,并在关键部分添加了注解:

rust 复制代码
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};
use sqlx::mysql::MySqlPool;
use redis::Client as RedisClient;
use std::sync::Arc;
use dotenv::dotenv;
use serde_json::json;
use std::env;

// 定义 User 结构体,用于序列化和反序列化
#[derive(Debug, Serialize, Deserialize)]
struct User {
    id: i32,
    name: String,
    email: String,
}

// 定义 AppState 结构体,用于存储数据库连接和 Redis 客户端
struct AppState {
    db: MySqlPool,
    redis: RedisClient,
}

// 获取单个用户
#[get("/users/{id}")]
async fn get_user(path: web::Path<i32>, data: web::Data<AppState>) -> impl Responder {
    let user_id = path.into_inner();
    let pool = &data.db;

    // 查询用户
    let query_result = sqlx::query_as!(
        User,
        r#"
        SELECT id, name, email FROM users WHERE id = ?
        "#,
        user_id
    )
    .fetch_optional(pool)
    .await;

    match query_result {
        Ok(Some(user)) => HttpResponse::Ok().json(user),
        Ok(None) => HttpResponse::NotFound().body("用户未找到"),
        Err(_) => HttpResponse::InternalServerError().body("获取用户时出错"),
    }
}

// 创建新用户
#[post("/users")]
async fn create_user(user: web::Json<User>, data: web::Data<AppState>) -> impl Responder {
    let pool = &data.db;

    // 插入用户
    let insert_result = sqlx::query!(
        r#"
        INSERT INTO users (name, email) VALUES (?, ?)
        "#,
        user.name,
        user.email
    )
    .execute(pool)
    .await;

    match insert_result {
        Ok(_) => HttpResponse::Created().json(&user),
        Err(_) => HttpResponse::InternalServerError().body("创建用户时出错"),
    }
}

// 获取所有用户
#[get("/users")]
async fn get_all_users(data: web::Data<AppState>) -> impl Responder {
    let pool = &data.db;

    // 查询所有用户
    let query_result = sqlx::query_as!(
        User,
        r#"
        SELECT id, name, email FROM users
        "#
    )
    .fetch_all(pool)
    .await;

    match query_result {
        Ok(users) => HttpResponse::Ok().json(users),
        Err(_) => HttpResponse::InternalServerError().body("获取用户时出错"),
    }
}

// 主函数,设置数据库连接和 Redis 客户端,并启动 HTTP 服务器
#[actix_web::main]
async fn main() -> std::io::Result<()> {
    dotenv().ok();

    // 从环境变量中读取数据库 URL
    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL 必须设置");
    // 创建数据库连接池
    let pool = MySqlPool::connect(&database_url).await.expect("创建连接池失败");

    // 从环境变量中读取 Redis URL
    let redis_url = env::var("REDIS_URL").expect("REDIS_URL 必须设置");
    // 创建 Redis 客户端
    let redis_client = RedisClient::open(redis_url).expect("创建 Redis 客户端失败");

    println!("服务器运行在 http://127.0.0.1:8880");

    // 启动 HTTP 服务器
    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(AppState {
                db: pool.clone(),
                redis: redis_client.clone(),
            }))
            .service(get_user)
            .service(create_user)
            .service(get_all_users)
    })
    .bind(("127.0.0.1", 8880))?
    .run()
    .await
}

设置环境变量

在项目的根目录下创建一个 .env 文件,并添加以下内容:

复制代码
DATABASE_URL=mysql://username:password@localhost/database_name
REDIS_URL=redis://127.0.0.1/

请将 usernamepassworddatabase_name 替换为你的 MySQL 数据库的实际值。

运行项目

最后,使用 Cargo 运行项目,并访问 http://127.0.0.1:8880 来测试 API 接口的功能。

sh 复制代码
cargo run

通过本教程,你将学会如何在 Windows 系统上使用 Actix-Web、SQLx 和 Redis 构建一个高性能的 Rust Web 服务,实现了用户管理系统的基本功能。

相关推荐
加班是不可能的,除非双倍日工资2 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi3 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip3 小时前
vite和webpack打包结构控制
前端·javascript
excel4 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国4 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼4 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy4 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
鼠鼠我捏,要死了捏4 小时前
生产环境Redis缓存穿透与雪崩防护性能优化实战指南
redis·cache
ZXT4 小时前
promise & async await总结
前端
Jerry说前后端4 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化