Rust请求追踪库tower-request-id的使用,为HTTP请求添加唯一标识符实现分布式追踪
Rust请求追踪库tower-request-id的使用,为HTTP请求添加唯一标识符实现分布式追踪
tower-request-id是一个用于tower生态(hyper, axum, warp等)的小型服务,为每个传入请求生成随机ID。
使用示例
将RequestIdLayer添加到axum中间件后,请求ID可以通过http::Request::extensions()获取。对于tracing集成,请参考日志记录示例。
完整示例代码
use axum::{
    routing::get,
    Router,
    extract::Request,
    middleware::{self, Next},
    response::IntoResponse,
};
use tower_request_id::{RequestId, RequestIdLayer};
use uuid::Uuid;
async fn handler(request: Request) -> impl IntoResponse {
    // 从请求扩展中获取请求ID
    let request_id = request.extensions().get::<RequestId>().unwrap();
    format!("Request ID: {}", request_id)
}
async fn log_request_id(request: Request, next: Next) -> impl IntoResponse {
    // 在中间件中获取请求ID
    let request_id = request.extensions().get::<RequestId>().unwrap();
    println!("Request ID in middleware: {}", request_id);
    
    next.run(request).await
}
#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/", get(handler))
        // 添加请求ID层
        .layer(RequestIdLayer::with_generator(|| Uuid::new_v4().to_string()))
        // 添加记录请求ID的中间件
        .layer(middleware::from_fn(log_request_id));
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}
代码说明
- 首先我们导入必要的模块和类型
 - 创建一个简单的handler函数,从中获取并返回请求ID
 - 创建一个中间件函数
log_request_id,演示如何在中间件中访问请求ID - 在main函数中:
- 创建路由
 - 添加
RequestIdLayer中间件层,使用UUID作为ID生成器 - 添加我们的日志记录中间件
 - 启动服务器
 
 
这个示例展示了如何:
- 为每个请求自动生成唯一ID
 - 在handler和中间件中访问这些ID
 - 使用自定义ID生成器(这里使用UUID)
 
许可证
本项目使用MIT许可证。
        
          1 回复
        
      
      
        Rust请求追踪库tower-request-id的使用:为HTTP请求添加唯一标识符实现分布式追踪
介绍
tower-request-id是一个Rust中间件库,用于为HTTP请求添加唯一标识符(Request ID),帮助实现分布式系统追踪。它基于tower生态构建,可以轻松集成到使用tower或axum等框架的应用中。
主要功能:
- 为每个HTTP请求生成唯一ID
 - 支持自定义ID生成策略
 - 可以从请求头中提取已有ID
 - 将ID注入到请求和响应中
 
完整示例代码
下面是一个完整的示例,展示了如何使用tower-request-id为HTTP请求添加唯一标识符:
use axum::{
    routing::get,
    Router,
    extract::Request,
    middleware,
    response::Response,
    body::Body
};
use tower::ServiceBuilder;
use tower_request_id::{RequestId, RequestIdLayer};
use uuid::Uuid;
use tracing::info;
use tower_http::trace::TraceLayer;
// 处理函数,显示请求ID
async fn handler(request_id: RequestId) -> String {
    info!(request_id = %request_id, "处理请求");
    format!("请求ID: {}", request_id)
}
// 自定义中间件,记录请求ID
async fn request_id_middleware(request: Request, next: middleware::Next) -> Response {
    let request_id = request.extensions().get::<RequestId>().unwrap().clone();
    info!(%request_id, "开始处理请求");
    
    let response = next.run(request).await;
    
    info!(%request_id, "请求处理完成");
    response
}
#[tokio::main]
async fn main() {
    // 初始化tracing日志
    tracing_subscriber::fmt().init();
    let app = Router::new()
        .route("/", get(handler))
        .layer(
            ServiceBuilder::new()
                // 添加请求ID层,使用UUID v4生成ID
                .layer(RequestIdLayer::new(
                    || Uuid::new_v4().to_string(),
                    "x-request-id".to_string(),
                ))
                // 添加HTTP追踪层
                .layer(TraceLayer::new_for_http())
                // 添加自定义中间件层
                .layer(middleware::from_fn(request_id_middleware))
        );
    let addr = "0.0.0.0:3000".parse().unwrap();
    info!("服务器启动,监听 {}", addr);
    
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}
代码说明
- 依赖配置 (Cargo.toml):
 
[dependencies]
axum = "0.7"
tower = "0.4"
tower-request-id = "0.3"
tower-http = "0.4"
uuid = { version = "1.3", features = ["v4"] }
tracing = "0.1"
tracing-subscriber = "0.3"
tokio = { version = "1.0", features = ["full"] }
- 核心组件:
 
RequestIdLayer: 生成请求ID的中间件层RequestId: 请求ID类型,可以从请求扩展中获取TraceLayer: HTTP请求追踪中间件tracing: 日志记录框架
- 工作流程:
 
- 每个请求到达时,
RequestIdLayer会生成唯一ID - 中间件和处理器可以通过请求扩展获取这个ID
 - ID会被自动添加到响应头中
 - 所有日志都会包含请求ID,便于追踪
 
最佳实践
- 一致性: 建议使用标准的请求头名称如
x-request-id - 传播: 调用下游服务时,确保传递请求ID
 - 日志: 在关键日志点记录请求ID
 - 格式: 使用UUID或ULID等标准格式,确保全局唯一性
 
这个完整示例展示了如何在实际项目中使用tower-request-id实现请求追踪,包括ID生成、日志记录和中间件集成。
        
      
                    
                  
                    
