使用 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 小时前
React Context 详解:从入门到性能优化
前端·vue.js·react.js
Sailing2 小时前
🚀 别再乱写 16px 了!CSS 单位体系已经进入“计算时代”,真正的响应式布局
前端·css·面试
喝水的长颈鹿2 小时前
【大白话前端 03】Web 标准与最佳实践
前端
爱泡脚的鸡腿2 小时前
Node.js 拓展
前端·后端
蚂蚁背大象4 小时前
Rust 所有权系统是为了解决什么问题
后端·rust
左夕4 小时前
分不清apply,bind,call?看这篇文章就够了
前端·javascript
布列瑟农的星空4 小时前
前端都能看懂的rust入门教程(五)—— 所有权
rust
Zha0Zhun4 小时前
一个使用ViewBinding封装的Dialog
前端
兆子龙4 小时前
从微信小程序 data-id 到 React 列表性能优化:少用闭包,多用 data-*
前端
滕青山4 小时前
文本行过滤/筛选 在线工具核心JS实现
前端·javascript·vue.js