我先按“它们分别处在网络栈的哪一层”来解释,这样最容易区分:rustls 负责 TLS 加密,hyper 负责 HTTP 协议,axum 负责 Web 应用路由与业务处理。
可以把它们理解成 Rust Web/网络服务开发里的三层东西:
浏览器 / 客户端 | HTTPS / TLS 加密层 ← rustls | HTTP 协议层 ← hyper | Web 路由 / 业务层 ← axum | 你的业务代码
1. hyper:底层 HTTP 库
hyper 是 Rust 生态里很核心的 HTTP 库,负责处理 HTTP/1、HTTP/2、请求、响应、连接等底层逻辑。官方定位是 Rust 的快速、安全 HTTP 实现;docs.rs 也说明它是偏底层的 HTTP building block。(hyper.rs)
你可以把 hyper 理解成:
用 Rust 直接处理 HTTP 协议的发动机。
它适合做:
HTTP 客户端 HTTP 服务端 反向代理 网关 流量转发 自定义协议代理 高性能网络中间件
例如你要写一个非常底层的 HTTP 代理:
use hyper::{Request, Response, Body};
async fn handle(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
println!("收到请求: {}", req.uri());
Ok(Response::new(Body::from("Hello from hyper")))
}
这种写法更接近“协议层”。你需要自己关心很多细节,比如连接、服务、body 流、错误处理等。
2. axum:Web 框架 / 路由框架
axum 是基于 Tokio 生态的 Web 框架,用于写 API、Web 服务、后端接口。官方文档描述它是一个关注易用性和模块化的 HTTP 路由与请求处理库。(Docs.rs)
你可以把 axum 理解成:
基于 hyper 之上的 Web 开发框架。
它适合做:
REST API 后台管理接口 登录接口 业务系统后端 微服务 Webhook 服务 本地 HTTP 服务
例如写一个接口:
use axum::{
routing::get,
Router,
};
async fn hello() -> &'static str {
"Hello from axum"
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(hello));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
访问:
http://127.0.0.1:3000/
返回:
Hello from axum
你不需要直接处理很多 HTTP 底层细节,axum 已经帮你抽象成了路由、handler、middleware、extractor 等概念。
3. rustls:TLS/HTTPS 加密库
rustls 是 Rust 写的 TLS 加密库,作用类似 OpenSSL,但更偏 Rust 原生、安全、现代。官方说明它实现 TLS 1.2 和 TLS 1.3,可用于客户端和服务端;rustls.dev 也强调协议处理使用内存安全 Rust。(GitHub)
你可以把 rustls 理解成:
给 TCP/HTTP 连接加 HTTPS 加密的安全层。
它适合做:
HTTPS 服务端 HTTPS 客户端 TLS 代理 安全网关 自定义加密通道 替代 OpenSSL
比如:
HTTP 服务: http://example.com
HTTPS 服务: https://example.com
↑
rustls 负责 TLS 加密
rustls 本身不负责路由,也不负责 HTTP 业务逻辑。它只负责 TLS 握手、证书、加密传输。
三者关系
最常见的关系是:
axum ↓ 使用 hyper ↓ 可以搭配 rustls
更准确地说:
| 名称 | 作用 | 层级 | 类比 |
|---|---|---|---|
| rustls | TLS/HTTPS 加密 | 传输安全层 | 给网络连接上锁 |
| hyper | HTTP 协议处理 | HTTP 协议层 | HTTP 发动机 |
| axum | 路由、接口、业务处理 | Web 框架层 | 后端开发框架 |
举个完整场景
假设你要写一个 HTTPS API 服务:
https://api.example.com/users/1
内部大概是这样:
客户端发起 HTTPS 请求
↓
rustls 处理 TLS 握手、证书、加密解密
↓
hyper 解析 HTTP 请求:GET /users/1
↓
axum 根据路由匹配到 /users/:id
↓
你的 handler 查询数据库并返回 JSON
对应业务代码可能是:
use axum::{
extract::Path,
routing::get,
Json,
Router,
};
use serde_json::{json, Value};
async fn get_user(Path(id): Path<u64>) -> Json<Value> {
Json(json!({
"id": id,
"name": "Alice"
}))
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/users/:id", get(get_user));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
这里你直接写的是 axum,但底层 HTTP 能力来自 hyper。如果要变成 HTTPS,就需要再接入 TLS 层,常见选择就是 rustls。
怎么选?
写普通 Web API
优先用:
axum
例如后台接口、登录服务、管理系统 API、Webhook 服务。
写 HTTP 代理、网关、底层转发
优先考虑:
hyper
例如你之前提到的 HTTP 代理、流量网关、按域名分流、流式转发等。
写 HTTPS / TLS / 证书相关
用:
rustls
例如 HTTPS 服务、TLS 终止、TLS 客户端、加密代理。
一句话总结
rustls 负责加密, hyper 负责 HTTP, axum 负责 Web 路由和业务开发。
对于你的网络工具方向,比较实用的组合是:
代理 / 网关底层:tokio + hyper + rustls 管理后台 / API:tokio + axum HTTPS 支持:rustl
Axum 底层用的是什么网络框架?
axum 底层主要不是“一个网络框架”,而是建立在这几个核心库之上:
axum ↓ Web 路由 / handler / extractor / middleware tower ↓ Service 抽象 / 中间件体系 hyper ↓ HTTP/1、HTTP/2 协议实现 tokio ↓ 异步运行时、TCP 网络 I/O 操作系统 socket
官方文档也明确说:axum 设计上就是和 Tokio + hyper 配合使用,不追求运行时和传输层无关。(Docs.rs) Tokio 官方发布 axum 0.7 时也说,axum 是用 tokio、tower、hyper 构建的 Web 框架。(Tokio)
简单理解
1. Tokio:最底层的异步网络 I/O
tokio 负责:
TCP 监听 异步 socket 读写 任务调度 定时器 异步运行时
比如这段代码:
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
这里就是 Tokio 在监听 TCP 端口。
2. hyper:HTTP 协议层
hyper 负责:
解析 HTTP 请求 生成 HTTP 响应 处理 HTTP/1、HTTP/2 处理连接上的请求/响应流
axum 本身不重新实现 HTTP 协议,它是 hyper 上面的一层。axum 的 crate 页面也说,axum 是 hyper 上相对薄的一层,性能接近 hyper。(Docs.rs)
3. tower:服务抽象和中间件层
tower 负责抽象:
Request -> Service -> Response
也就是说,一个 Web 服务可以被看成:
收到请求 ↓ 经过若干 middleware ↓ 进入 handler ↓ 返回响应
axum 的中间件体系不是自己单独造的,而是集成 tower,因此 tower 和 tower-http 的中间件生态可以直接用于 axum。(Docs.rs)
常见中间件包括:
CORS 日志 tracing 压缩 compression 超时 timeout 限流 rate limit 认证 auth
4. axum:Web 框架层
axum 主要负责:
路由 Router handler extractor response 转换 middleware 组合 状态共享 State
例如:
use axum::{routing::get, Router};
async fn hello() -> &'static str {
"Hello from axum"
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(hello));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
这段代码背后的调用关系大概是:
tokio::net::TcpListener 监听 TCP
↓
axum::serve 接收连接
↓
hyper 处理 HTTP 协议
↓
tower 把请求交给 Service
↓
axum Router 匹配路由
↓
hello handler 执行业务逻辑
所以一句话回答
axum 底层主要用的是:
tokio + hyper + tower
更准确地说:
| 层级 | 库 | 作用 |
|---|---|---|
| 异步运行时 / TCP | tokio | 负责异步网络 I/O |
| HTTP 协议 | hyper | 负责 HTTP/1、HTTP/2 |
| 服务抽象 / 中间件 | tower | 负责 Service、Layer、Middleware |
| Web 框架 | axum | 负责路由、handler、extractor |
如果你是要做普通后端 API,用 axum 就够了;如果你要做代理、网关、流量转发这种更底层的东西,通常会更直接地使用 hyper + tokio,必要时再加 rustls 做 HTTPS/TLS。