设计 API 网关
问题
如何用 Rust 设计一个 API 网关?
答案
架构设计
基于 Axum + Tower 的网关
use axum::{Router, middleware, routing::any};
use tower::ServiceBuilder;
use std::collections::HashMap;
/// 路由配置
struct GatewayConfig {
routes: Vec<RouteRule>,
}
struct RouteRule {
prefix: String, // e.g. "/api/users"
upstream: String, // e.g. "http://user-service:3000"
rate_limit: Option<u32>, // 每秒请求数
auth_required: bool,
}
fn build_gateway(config: GatewayConfig) -> Router {
let mut router = Router::new();
for rule in config.routes {
let upstream = rule.upstream.clone();
// 为每个路由创建处理函数
let handler = any(move |req: axum::extract::Request| {
let upstream = upstream.clone();
async move {
// 转发请求到上游服务
let client = reqwest::Client::new();
let path = req.uri().path_and_query()
.map(|pq| pq.as_str())
.unwrap_or("/");
let url = format!("{}{}", upstream, path);
match client.request(req.method().clone(), &url)
.headers(req.headers().clone())
.send()
.await
{
Ok(resp) => {
let status = resp.status();
let body = resp.text().await.unwrap_or_default();
(status, body).into_response()
}
Err(_) => {
axum::http::StatusCode::BAD_GATEWAY.into_response()
}
}
}
});
router = router.route(&format!("{}/*rest", rule.prefix), handler);
}
// 全局中间件链
router.layer(
ServiceBuilder::new()
.layer(middleware::from_fn(logging_middleware))
.layer(middleware::from_fn(metrics_middleware))
)
}
网关核心功能
| 功能 | 实现方式 |
|---|---|
| 路由转发 | 前缀匹配 → 上游服务 |
| 认证 | JWT 验证中间件 |
| 限流 | Tower RateLimit / 自定义令牌桶 |
| 熔断 | Tower Circuit Breaker |
| 请求改写 | 中间件修改 Header/Body |
| 协议转换 | HTTP ↔ gRPC |
| 负载均衡 | Round-Robin / P2C |
| 监控 | Prometheus metrics |
常见面试问题
Q1: API 网关与反向代理的区别?
答案:
| 维度 | 反向代理 | API 网关 |
|---|---|---|
| 关注点 | 流量转发 | 业务治理 |
| 功能 | 负载均衡、缓存 | 认证、限流、熔断、协议转换 |
| 路由 | URL → 后端 | URL + Header + 规则 → 微服务 |
| 配置 | 静态 | 动态(配置中心) |
| 典型实现 | Nginx | Kong、Envoy、自研 |
API 网关 = 反向代理 + 业务治理层。