AFaster:一个开箱即用的 Rust 高性能后端框架模板

93 阅读6分钟

AFaster:一个开箱即用的 Rust 高性能后端框架模板

基于 afast 构建,内置 25+ 业务模块,从微信支付到链路追踪,一行配置即可启用。

前言

在日常后端开发中,我们反复做的事情往往不是写核心业务逻辑,而是搭架子——接数据库、配 JWT、对接微信支付、接入 OSS 存储、写日志、搞限流……这些"胶水代码"每个项目都要来一遍,耗时且容易出错。

AFaster 就是为了解决这个问题而生的:它是一个基于 Rust 的后端框架模板,把常见的业务模块全部预置好,通过 Cargo feature 按需启用,通过 config.toml 统一配置,让你在 main() 里写几行代码就能跑起一个功能完备的后端服务。

use afaster::AFaster;

#[tokio::main]
async fn main() {
    AFaster::new("config.toml".to_string()).await
        .unwrap()
        .run()
        .await;
}

是的,就这么点代码。下面聊聊它背后的设计和能力。

设计理念

1. Feature-driven,按需组合

AFaster 的所有功能模块都通过 Cargo feature 控制。不需要微信支付?不启用 wx-pay-* 就行,编译产物不会包含任何相关代码。需要 Redis + PostgreSQL + 邮件发送?组合启用即可:

[dependencies]
afaster = { version = "0.0.3", features = ["redis", "db-postgres", "email"] }

这种设计带来了两个直接好处:

  • 编译产物精简——未启用的模块不会被编译进来
  • 依赖冲突可控——每个 feature 只拉取自己需要的依赖

2. 统一配置,链式构建

所有模块的配置统一放在 config.toml 中,结构清晰:

[backend]
host = "0.0.0.0"
port = 5000

[redis]
host = "127.0.0.1"
port = 6379

[wx_pay]
mch_id = "your_mch_id"
app_id = "your_app_id"
# ...

而在代码侧,AFaster 提供链式 Builder API 来注册回调、配置行为:

AFaster::new("config.toml".to_string()).await
    .unwrap()
    .with_github_oauth2(|g| g.with_github_callback(|(state, result, oauth_state)| {
        async move {
            // 处理 GitHub OAuth2 登录回调
            Ok(result)
        }
    }))
    .with_wx_virtual_pay(|w| w
        .with_goods_deliver_callback(|(state, notify)| {
            async move {
                // 处理虚拟支付道具发货
                Ok(afaster::wx_virtual_pay::WxPayNotifyResult::success())
            }
        })
    )
    .run()
    .await;

3. 静态文件服务内置

前后端分离项目中,SPA 部署是刚需。AFaster 内置了静态文件服务模块,支持两种模式:

运行时目录模式——从磁盘读取:

AFaster::new("config.toml".to_string()).await
    .unwrap()
    .with_serve(Serve::from_dir("./dist").with_spa(true))
    .run()
    .await;

编译期嵌入模式——整个目录打包进二进制,部署时只需一个文件:

AFaster::new("config.toml".to_string()).await
    .unwrap()
    .with_serve(Serve::from_embedded(include_dir!("$CARGO_MANIFEST_DIR/dist")).with_spa(true))
    .run()
    .await;

SPA 模式下,未匹配的路径会自动回退到 index.html,前端路由不再 404。

功能模块全景

AFaster 目前内置 25+ 个功能模块,覆盖了后端开发的方方面面。按类别梳理如下:

认证与安全

JWT 令牌认证

# config.toml
[token]
expire = 3600
secret = "your-secret-key"
#[handler(desc("接口名称"), rate_limit("接口限流策略名称"))]
async fn api(state: State<AppState>, req: Data<Req>) -> Result<Resp> {
    // 所有模块都可以通过 state 调用
    
    // 生成 Token
    let token = state.token.create_token(user_id, &user_data)?;
    // 验证并提取数据
    let claims = state.token.verify_token::<UserData>(&token)?;
}

Argon2 密码哈希

use afaster::argon2;

let hash = argon2::hash("my_password")?;
let ok = argon2::verify("my_password", &hash)?;

RBAC 权限管理

// 实现 RbacStore trait
impl RbacStore for MyStore {
    fn check_permission(&self, user_id: i64, code: &str) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + '_>> {
        // 查询权限逻辑
    }
}

// 在 handler 中使用
if !rbac.check_permission(user_id, "post:create").await? {
    return Err(afaster::Error::custom(42803, "权限不足"));
}

限流

# config.toml
[[rate_limit.policies]]
id = "login"
max_requests = 5
window_seconds = 60
algorithm = "sliding_window"
key = "ip"
#[handler(desc("登录接口"), rate_limit("login"))]
async fn login(state: State<AppState>, req: Data<LoginReq>) -> Result<LoginResp> {
    // 框架自动按 "login" 策略限流
}

HTTPS / WSS

# config.toml
[backend.tls]
port = 443
cert_path = "/etc/ssl/cert.pem"
key_path = "/etc/ssl/key.pem"
// 无需修改代码,框架自动启用 HTTPS
AFaster::new("config.toml".to_string()).await.unwrap().run().await;

微信生态

这是 AFaster 最用心的部分之一,覆盖了微信体系下的主流场景:

微信登录(小程序/APP/网页)

# config.toml
[wxlogin]
mini_id = "wx1234567890"
mini_secret = ""
app_id = "wx1234567890"
app_secret = ""
// 小程序登录
let result = state.wxlogin.mini_login(&code).await?;
let openid = result.openid;

// APP 登录
let result = state.wxlogin.app_login(&code).await?;
let access_token = result.access_token;

微信支付(H5/Native/APP/小程序/JSAPI)

# config.toml
[wx_pay]
mch_id = "1600000000"
app_id = "wx_your_app_id"
api_v3_key = "your_api_v3_key"
private_key = """-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
"""
serial_no = "your_cert_serial_no"
notify_url = "https://your-domain.com/api/wx-pay/notify"
// H5 支付
let result = state.wx_pay.prepay_h5(
    "ORDER_20260603_001", "测试商品", 100,
    "123.123.123.123", "Wap", "https://example.com",
).await?;
println!("h5_url: {}", result.h5_url);

// Native 支付
let result = state.wx_pay.prepay_native(
    "ORDER_20260603_001", "测试商品", 100,
).await?;
println!("code_url: {}", result.code_url);

微信公众号

use afaster::wx_official::TemplateDataBuilder;

// 模板消息
let data = TemplateDataBuilder::new()
    .value("name01", "张三")
    .value("amount01", "¥100")
    .build();

let msgid = state.wx_official.send_template_message(
    "openid",                    // 接收者
    "template_id",               // 模板 ID
    data,                        // 模板数据
    Some("https://example.com"), // 跳转链接 (可选)
    None,                        // 跳转小程序 (可选)
).await?;

// 网页授权
let result = state.wx_official.oauth2_access_token(&code).await?;

每种支付方式都有独立的 feature 和回调机制,互不干扰。

云服务集成

阿里云 OSS

# config.toml
[oss]
access_key_id = ""
access_key_secret = ""
region = "cn-hangzhou"
bucket = ""
let url = state.oss.get_signed_download_url("abc123.png").await?;
let url = state.oss.get_signed_upload_url("abc123.png", "image/png").await?;

支付宝电脑网站支付

# config.toml
[ali_pay]
app_id = "2014072300007148"
private_key = """-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
"""
alipay_public_key = """-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
"""
notify_url = "https://example.com/ali/pay/notify"
use afaster::ali_pay::PagePayRequest;

let html = state.ali_pay.page_pay(&PagePayRequest {
    out_trade_no: "ORDER_001".into(),
    total_amount: "100.00".into(),
    subject: "测试商品".into(),
    ..Default::default()
}).await?;

阿里云短信

# config.toml
[sms_ali]
access_key_id = ""
access_key_secret = ""
sign_name = "你的签名"
template_code = "SMS_123456"
let resp = state.sms_ali.send_code("13800138000", "1234").await?;

腾讯云 COS

# config.toml
[cos]
secret_id = ""
secret_key = ""
bucket = "mybucket-1250000000"
region = "ap-guangzhou"
let url = state.cos.get_signed_download_url("abc123.png").await?;
let url = state.cos.get_signed_upload_url("abc123.png", "image/png").await?;

腾讯云短信

# config.toml
[sms_tencent]
secret_id = ""
secret_key = ""
sdk_app_id = "1400000000"
sign_name = "你的签名"
template_id = "123456"
let resp = state.sms_tencent.send_code("13800138000", "1234", Some("5")).await?;

腾讯地图

# config.toml
[tmap]
key = "your_tencent_map_key"
let res = tmap.geocoder("北京市海淀区", Some("北京")).await?;
let res = tmap.direction_driving("39.984154,116.307490", "39.904989,116.405285", None, None).await?;

数据层

多数据库支持(PostgreSQL / SQLite / MySQL)

# config.toml
[postgres]
host = "127.0.0.1"
port = 5432
user = "postgres"
pass = ""
name = "afaster"
// 单数据库时
let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
    .fetch_one(state.db.pool())
    .await?;

// 多数据库时
let pg_pool = state.db.pg();
let sqlite_pool = state.db.sqlite();

Redis / Valkey

# config.toml
[redis]
host = "127.0.0.1"
port = 6379
state.redis.set("key", "value", Some(3600)).await?;
let val: Option<String> = state.redis.get("key").await?;
state.redis.hset("user:1", "name", "Alice").await?;
let name: Option<String> = state.redis.hget("user:1", "name").await?;

内存 KV

use afaster::memkv::MemKV;

let kv = MemKV::new();
kv.set("name", b"hello".to_vec(), Some(Duration::from_secs(60))).await?;
let v: Option<Vec<u8>> = kv.get("name").await?;

布隆过滤器

# config.toml
[bloom]
expected_items = 100000
false_positive_rate = 0.01
auto_check_key = "ip"
use afaster::bloom::BloomFilter;

// 手动模式
if bloom.check("some_key") {
    return Err(afaster::Error::custom(41001, "Duplicate request"));
}
bloom.add("some_key");

文件处理

本地文件服务

# config.toml
[file]
root = "./uploads"
max_size = 10485760
allowed = ["jpg", "png", "gif", "pdf"]
use afaster::FileService;

let fs = FileService::new(&config.file)?;
let info = fs.upload("docs/readme.txt", data)?;
let data = fs.download("docs/readme.txt")?;
let url = fs.url("docs/readme.txt")?;

Excel / CSV

use afaster::Excel;

// 读取 Excel/CSV(自动识别格式)
let data = Excel::read_path("data.xlsx", None)?;
let data = Excel::read_path("data.csv", None)?;

// 读取为 JSON
let json = Excel::read_to_json("users.xlsx", None)?;

// 写入 Excel
let bytes = Excel::write_xlsx(&headers, &rows)?;

PDF 生成

use afaster::{Pdf, TextStyle};

let font = std::fs::read("fonts/SourceHanSansSC-Regular.otf")?;
let bytes = Pdf::new("发票")
    .font_regular(&font)
    .text("增值税普通发票", TextStyle::title(), 60.0, 270.0)
    .text("金额: ¥12,493.00", TextStyle::body().bold(), 15.0, 230.0)
    .finish()?;
std::fs::write("invoice.pdf", bytes)?;

图片生成

use afaster::{Image, ImageTextStyle, ImageColor};

let font = std::fs::read("fonts/SourceHanSansSC-Regular.otf")?;
let bytes = Image::new(800, 600)
    .font_regular(&font)
    .background(ImageColor::white())
    .draw_rect(0, 0, 800, 80, ImageColor::blue())
    .draw_text("用户报告", 20, 20, ImageTextStyle::title().color(ImageColor::white()))
    .finish()?;
std::fs::write("poster.png", bytes)?;

消息通知

邮件发送

# config.toml
[email]
default = "main"

[[email.accounts]]
id = "main"
host = "smtp.qq.com"
port = 465
user = ""
pass = ""
from = ""
name = ""
state.email.send("to@example.com", "标题", "<h1>正文</h1>", &[]).await?;
state.email.send_text("to@example.com", "标题", "纯文本正文", &[]).await?;

推送服务(个推/极光/小米)

# config.toml
[push.getui]
app_id = ""
app_key = ""
master_secret = ""
use afaster::push::{PushTarget, Notification};

let target = PushTarget::Cid("regid".to_string());
let notification = Notification::new("标题", "内容").url("https://example.com");
state.push.getui.send(target, notification, None).await?;

SSE 实时推送

use afaster::Socket;

// 注册 SSE 连接
let conn_id = socket.register_sse(Some("user_1001"), sse_sender, None).await;

// 按用户 ID 推送
socket.send_to_id("user_1001", "新消息通知").await;

// 按分组推送
socket.send_to_group("vip_users", "专属优惠").await;

// 广播
socket.broadcast("系统公告").await;

工具集

Snowflake ID 生成器

# config.toml
[snow]
worker_id = 1
datacenter_id = 1
let id = state.snow.next_id().await;
let id_str = state.snow.next_id_str().await;
let order_no = state.snow.next_id_prefix("ORD").await;

定时任务

AFaster::new("config.toml".into()).await?
    .with_scheduler(|s| {
        s.add_task("cleanup", "*/5 * * * *", |state, name, times| async move {
            println!("[{}] 第 {} 次执行", name, times);
        }).unwrap();
        s
    })
    .run()
    .await;

链路追踪

# config.toml
[tracing]
service_name = "afaster"
db_path = "tracing.db"
// 无需修改代码,框架自动为每个请求创建 Span
// 启动后访问 /tracing 查看 Web UI
AFaster::new("config.toml".to_string()).await.unwrap().run().await;

高德地图

# config.toml
[amap]
key = "your_amap_key"
let res = amap.geocode("北京市朝阳区阜通东大街6号", Some("北京")).await?;
let res = amap.direction_walking("116.397428,39.90923", "116.407428,39.91923").await?;

实战:用 AFaster 搭一个博客系统

AFaster 的 example/ 目录下就有一个完整的多人博客系统示例,展示了如何用框架快速搭建业务。它包含三个 Service:

  • user:公开接口(注册、登录、浏览文章)
  • user_backend:用户后台(管理自己的文章、评论)
  • admin:管理员接口(审核、用户管理、分类标签管理)

通过 RBAC 实现权限控制,每个接口都有明确的权限码,框架自动完成鉴权:

// RBAC 存储实现(SQLite)
impl RbacStore for SqliteRbacStore {
    fn check_permission(&self, user_id: i64, permission_code: &str)
        -> Pin<Box<dyn Future<Output = Result<bool>> + Send + '_>>
    {
        // 查询用户角色关联的权限表
    }
}

这个示例涵盖了数据库操作、JWT 认证、RBAC 权限、分页查询等典型后端场景,是很好的学习参考。

可交互的 API 调试文档

Screenshot from 2026-06-16 20-54-15.png

错误码设计

AFaster 采用 5 位数字错误码,设计巧妙:

  • 第 1 位:4 = 用户错误,5 = 内部错误
  • 第 2-3 位:模块编号(如 28 = 某个具体模块)
  • 第 4-5 位:模块内序号

例如 42801 表示"模块 28 的第 1 个用户错误",52803 表示"模块 28 的第 3 个内部错误"。这种设计让错误码既有序又可读,排查问题时一眼就能定位到模块。

链路追踪

AFaster 的链路追踪模块(trace)值得一提。它支持三种后端:

  • trace-sqlite:存储到 SQLite,适合单机部署
  • trace-http:通过 HTTP 上报,适合集中式收集
  • trace-tcp:通过 TCP 上报,性能更好

更贴心的是,它还内置了一个 Web UI,可以直接在浏览器中查看链路瀑布图、Span 树、耗时分布等。对于排查性能问题非常有帮助。

Screenshot from 2026-06-16 20-48-51.png

Screenshot from 2026-06-16 20-49-00.png

代码生成

启用 afast-ts / afast-js / afast-kt / afast-rs 等 feature 后,AFaster 可以自动生成客户端代码(TypeScript / JavaScript / Kotlin / Rust),让前后端对接更加顺畅。这意味着你定义好 Service 接口后,前端可以直接拿到类型安全的 SDK。

总结

AFaster 不是要替代 Actix-web 或 Axum 这样的通用框架,而是在它们之上提供一层业务模板。它的定位很明确:

  • ✅ 快速搭建功能完备的后端服务
  • ✅ 内置微信生态、云服务、支付等中国特色业务模块
  • ✅ Feature-driven 按需组合,不引入多余依赖
  • ✅ 统一配置 + 链式 API,降低心智负担
  • ✅ 内置链路追踪、限流、RBAC 等生产级能力

如果你正在用 Rust 做后端开发,且项目涉及微信生态或常见的业务模块集成,AFaster 值得一试。它能帮你跳过大量的"轮子搭建"阶段,直接进入核心业务开发。

项目地址:github.com/ahriknow/af…

文档:afaster.ahriknow.help


AFaster 基于 MIT 协议开源,欢迎 Star 和 PR。