2026-01-29 14:37:31 +08:00
2026-01-29 14:37:31 +08:00
2026-01-29 14:37:31 +08:00
2026-01-29 14:37:31 +08:00
2026-01-29 14:37:31 +08:00
2026-01-29 14:37:31 +08:00
2026-01-29 14:37:31 +08:00

Microservice Common Lib (Rust)

这是微服务架构的通用基础库,旨在统一所有服务的错误处理标准、日志格式以及分布式链路追踪。

核心特性

  • 统一错误处理 (Error):
    • 基于 thiserroranyhow 的最佳实践。
    • 双 Token 支持: 明确区分 AccessTokenExpired (20001) 和 RefreshTokenExpired (20002)。
    • Axum 集成: 实现了 IntoResponse,自动将错误转换为标准 JSON 格式并设置正确的 HTTP 状态码。
  • 可观测性 (Telemetry):
    • 基于 tracing 生态。
    • 支持 JSON 结构化日志 (适配 ELK/Loki)。
    • 支持 控制台 + 文件双写
    • 支持 非阻塞 (Non-blocking) 异步日志写入与按天滚动。
  • 模块化设计: 通过 Feature Flags 按需引入。

🚀 发布指南

你可以选择将此库发布到私有 Cargo 仓库 (Kellnr),或者直接作为 Git 依赖发布到 Gitea。

方法一:发布到 Kellnr (推荐)

Kellnr 是一个私有的 Crates.io 镜像与仓库。

1. 配置本地 Cargo

在本项目根目录(或全局 ~/.cargo/config.toml)创建/修改 .cargo/config.toml,注册你的私有仓库:

# .cargo/config.toml
[registries.kellnr]
# 注册表名称自定义,这里叫 "kellnr"
index = "sparse+https://kellnr.shay7sev.site/api/v1/crates/"

[net]
git-fetch-with-cli = true

2. 登录认证

使用你的 Kellnr 账户 Token 进行登录(只需执行一次):

cargo login --registry kellnr <YOUR_AUTH_TOKEN>

3. 修改 Cargo.toml

确保 Cargo.toml 中配置了禁止发布到公网,并指定了私有仓库:

[package]
name = "common-telemetry"
version = "0.1.0"
# ...
publish = ["kellnr"] # 关键:防止误发到 crates.io

4. 执行发布

cargo publish --registry kellnr

方法二:推送到 Gitea (Git 依赖)

如果你不想走 Cargo Registry 流程,可以直接作为 Git 仓库使用。

# 初始化 git (如果尚未初始化)
git init
git branch -M main

# 添加远程仓库 (替换为你的实际仓库地址)
git remote add origin ssh://git@gitea.shay7sev.site:2222/admin/common-telemetry.git

# 推送代码
git add .
git commit -m "Initial commit"
git push -u origin main

📦 如何在其他服务中使用

假设你要在 user-service 中使用此库。

1. 引入依赖

方式 A: 通过 Kellnr 引入 (如果已发布)

user-serviceCargo.toml 中:

[dependencies]
# 指定 registry
common-telemetry = { version = "0.1", registry = "kellnr", features = ["full"] }

注意:使用此方式,user-service 项目也需要在 .cargo/config.toml 中配置 registry 地址。

方式 B: 通过 Gitea (Git) 引入 (简单直接)

user-serviceCargo.toml 中:

[dependencies]
# 指定 git 地址
common-telemetry = { git = "ssh://git@gitea.shay7sev.site:2222/admin/common-telemetry.git", branch = "main", features = ["full"] }

2. 代码集成示例

A. 初始化日志 (main.rs)

use common_lib::telemetry::{self, TelemetryConfig};

#[tokio::main]
async fn main() {
    // 1. 配置
    let config = TelemetryConfig {
        service_name: "user-service".into(),
        log_level: "info".into(), // 或 "debug,sqlx=error"
        log_to_file: true,        // 生产环境建议开启
        log_dir: Some("./logs".into()),
        log_file: Some("user.log".into()),
    };

    // 2. 初始化 Tracing
    // !!! 警告:必须将 guard 赋值给一个变量 (_guard),并保持它在 main 函数整个生命周期内存活
    // 否则日志文件写入线程会被立即销毁!
    let _guard = telemetry::init(config);

    tracing::info!("User Service started success!");

    // ... 启动 Axum ...
}

B. 错误处理与响应 (Handler)

use axum::{Json, response::IntoResponse};
use common_lib::AppError; // 引入统一错误

async fn get_profile(token: String) -> Result<Json<UserProfile>, AppError> {
    // 模拟Token 过期
    if token_is_expired(&token) {
        // 直接返回枚举,库会自动处理为 JSON Response (Code: 20001)
        // 并且会自动打印 Error 级别的日志
        return Err(AppError::AccessTokenExpired);
    }
    
    // 模拟:数据库错误
    let user = db::find_user().await
        .map_err(|e| AppError::DbError(e.to_string()))?;

    Ok(Json(user))
}

⚙️ 功能模块说明 (Feature Flags)

为了减少编译时间和依赖大小,你可以按需开启功能:

Feature 说明 包含依赖
default 默认开启所有功能 full
full 全功能集合 error, telemetry
error 仅使用错误处理与 HTTP 响应 thiserror, axum, serde
telemetry 仅使用日志与链路追踪 tracing, tracing-subscriber, tracing-appender

示例 (只用日志模块):

common-telemetry = { version = "0.1", default-features = false, features = ["telemetry"] }

📝 错误码对照表

前端开发请参考以下业务状态码 (Code)

Code 枚举 含义 前端建议动作
0 Success 成功 -
10000 ServerError 服务器内部错误 提示“系统繁忙”
10001 BadRequest 请求参数错误 提示错误信息
20000 Unauthorized 未授权/签名无效 跳转登录
20001 AccessTokenExpired Access Token 过期 使用 Refresh Token 静默刷新
20002 RefreshTokenExpired Refresh Token 过期 强制登出,跳转登录页
20003 PermissionDenied 权限不足 提示无权访问

🛠 开发注意事项

  1. Cargo.lock: 本项目已将 Cargo.lock 加入 .gitignore,这是作为 Library 的最佳实践。
  2. 测试: 运行集成测试以验证全链路功能。
    # 使用 --nocapture 查看详细步骤打印
    cargo test -- --nocapture
    
Description
No description provided
Readme 75 KiB
Languages
Rust 96%
TypeScript 4%