Tower for Rust:完整指南与示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

什么是 Tower,为什么需要它?

\n\n

Tower 是 Rust 生态系统中的一个基础库,提供了用于构建模块化、可组合的异步网络服务和中间件(middleware)的抽象。它不是一个现成的 HTTP 框架(如 Actix-web 或 Axum),而是它们的“构建材料”。例如,Axum 就是构建在 Tower 之上的。

\n\n

Tower 的核心思想是 Service 特征(trait),它代表一个异步函数,将请求(Request)转换为响应(Response)。Tower 中的中间件(或“Layer”)是一种将一个服务包装在另一个服务中的方式,从而在不修改原始服务代码的情况下,为其添加额外的行为(如日志记录、身份验证、超时、负载均衡等)。

\n\n

为什么需要它?

\n
    \n
  • 模块化:您可以将复杂的请求处理逻辑分解为小型、独立、可重用的组件(服务和中间件)。
  • \n
  • 可组合性:中间件可以轻松组合,像层(layers)一样相互叠加。
  • \n
  • 异步性:Tower 专为与异步 Rust(tokio、async-std)一起工作而设计,并支持 futures。
  • \n
  • 可测试性:每个组件都可以独立测试。
  • \n
\n\n

安装 Tower

\n\n

Tower 是一个 Rust 库,因此通过包管理器 Cargo 安装。将依赖项添加到您的 Cargo.toml 文件中:

\n\n
[dependencies]\ntower = { version = "0.4", features = ["full"] } # "full" 包含所有功能\ntokio = { version = "1", features = ["full"] } # 用于异步运行时\n
\n\n

之后,在终端中执行以下命令:

\n
cargo build
\n\n

该库将与您的项目一起下载并编译。

\n\n

快速入门:您的第一个服务和中间件

\n\n

让我们创建一个简单的服务,它接收一个字符串并返回相同的大写字符串。然后,将其包装在一个记录每个请求的中间件中。

\n\n
use std::convert::Infallible;\nuse std::task::{Context, Poll};\nuse tower::{Service, Layer, ServiceBuilder};\nuse tower::layer::util::Identity;\nuse std::future::{Ready, ready};\n\n// 1. 定义我们的服务\n#[derive(Clone)]\nstruct MyService;\n\nimpl<Request> Service<Request> for MyService {\n    type Response = String;\n    type Error = Infallible;\n    type Future = Ready<Result<Self::Response, Self::Error>>;\n\n    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        Poll::Ready(Ok(()))\n    }\n\n    fn call(&mut self, req: Request) -> Self::Future {\n        // 直接返回一个字符串\n        ready(Ok(format!("Hello from service! Request: {:?}", std::any::type_name::<Request>())))\n    }\n}\n\n// 2. 定义用于日志记录的中间件\n#[derive(Clone)]\nstruct LogMiddleware;\n\nimpl<S> Layer<S> for LogMiddleware {\n    type Service = LogService<S>;\n\n    fn layer(&self, inner: S) -> Self::Service {\n        LogService { inner }\n    }\n}\n\n#[derive(Clone)]\nstruct LogService<S> {\n    inner: S,\n}\n\nimpl<S, Request> Service<Request> for LogService<S>\nwhere\n    S: Service<Request>,\n    S::Future: std::marker::Send,\n    Request: std::fmt::Debug,\n{\n    type Response = S::Response;\n    type Error = S::Error;\n    type Future = S::Future;\n\n    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        self.inner.poll_ready(cx)\n    }\n\n    fn call(&mut self, req: Request) -> Self::Future {\n        printl                    

推荐