# 📘 Limiteron API 参考
本文档完整描述 Limiteron 的公开 API,包括限流器、封禁管理、配额控制、熔断器、Governor、匹配器、存储后端、Admin REST API、配置加载与错误类型。所有签名与 `src/` 源码一致(版本 0.3.0-rc.7)。使用方法与场景示例请见 [用户指南](USER_GUIDE.md)。
[🏠 首页](../README.md) • [📖 用户指南](USER_GUIDE.md) • [❓ 常见问题](FAQ.md)
---
## 📋 目录
<details open>
<summary>📑 目录</summary>
- [🧭 概述](#-概述)
- [🚦 限流器](#-限流器)
- [Limiter trait](#limiter-trait)
- [TokenBucketLimiter](#tokenbucketlimiter)
- [GcraLimiter](#gcralimiter)
- [其他限流算法](#其他限流算法)
- [已弃用导出](#已弃用导出)
- [🚪 封禁管理](#-封禁管理)
- [BanManager](#banmanager)
- [BanTarget 与 BanSource](#bantarget-与-bansource)
- [BanFileLoader](#banfileloader)
- [📊 配额控制](#-配额控制)
- [🔌 熔断器](#-熔断器)
- [🔁 重试](#-重试)
- [🎛️ Governor](#️-governor)
- [🔍 匹配器](#-匹配器)
- [💾 存储后端](#-存储后端)
- [MemoryStorage](#memorystorage)
- [StorageFactory](#storagefactory)
- [🌐 Admin REST API](#-admin-rest-api)
- [POST /api/v1/ban](#post-apiv1ban)
- [DELETE /api/v1/ban/{target}](#delete-apiv1bantarget)
- [⚙️ 配置加载](#️-配置加载)
- [🚨 错误处理](#-错误处理)
- [📐 类型定义](#-类型定义)
- [💡 使用示例](#-使用示例)
</details>
---
## 🧭 概述
| 设计原则 | 说明 |
|---------|------|
| 简单 | 核心类型收敛在少数模块,`prelude` 一行导入常用类型 |
| 安全 | 类型安全,默认特性为空、零外部存储依赖 |
| 可组合 | `Limiter` trait 统一算法接口,决策链按优先级级联 |
| 文档完善 | 全部公开 API 带文档注释,docs.rs 在线可查 |
带特性门控的 API 在对应小节标注所需 feature。`default = []` 时仅核心限流可用。
---
## 🚦 限流器
限流器模块位于 `limiteron::limiters`,全部实现统一的 `Limiter` trait。
### Limiter trait
```rust
#[async_trait]
pub trait Limiter: Send + Sync {
/// 消费指定成本,返回是否允许
async fn allow(&self, cost: u64) -> Result<bool, LimiteronError>;
/// 非消费预检:返回标准限流头数据,绝不修改限流器状态
async fn peek(&self, cost: u64) -> Result<RateLimitSnapshot, LimiteronError>;
/// 非消费查询剩余额度
async fn remaining(&self) -> Result<RateLimitSnapshot, LimiteronError>;
/// 检查是否允许(接受 key 参数,供宏生成代码使用)
async fn check(&self, key: &str) -> Result<(), LimiteronError>;
}
```
`peek` / `remaining` 返回的 `RateLimitSnapshot` 对应 IETF `RateLimit-*` 头数据:
| 字段 | 类型 | 说明 |
|------|------|------|
| `limit` | `u64` | 窗口/桶容量上限(`RateLimit-Limit`) |
| `remaining` | `u64` | 当前剩余额度(`RateLimit-Remaining`) |
| `reset_secs` | `u64` | 距额度重置的秒数(`RateLimit-Reset`) |
---
### TokenBucketLimiter
令牌桶限流器。
#### `TokenBucketLimiter::new()`
```rust
pub fn new(capacity: u64, refill_rate: u64) -> Self
```
| 参数 | 类型 | 说明 |
|------|------|------|
| `capacity` | `u64` | 桶容量(最大令牌数) |
| `refill_rate` | `u64` | 每秒补充的令牌数 |
#### `TokenBucketLimiter::allow()`
```rust
pub async fn allow(&self, cost: u64) -> Result<bool, LimiteronError>
```
返回 `Ok(true)` 允许、`Ok(false)` 被限流;成本为 0 或超过 `MAX_COST` 时返回 `ConfigError`。
**示例:**
```rust
use limiteron::limiters::TokenBucketLimiter;
let limiter = TokenBucketLimiter::new(10, 1); // 10 个令牌,每秒补充 1 个
match limiter.allow(1).await {
Ok(true) => println!("✅ 请求允许"),
Ok(false) => println!("❌ 请求被限流"),
Err(e) => println!("❌ 错误: {:?}", e),
}
```
---
### GcraLimiter
GCRA(Generic Cell Rate Algorithm)限流器,需要启用 `gcra` 特性。位于 `limiteron::limiters::GcraLimiter`。
#### `GcraLimiter::new()`
```rust
pub fn new(capacity: u64, refill_interval_us: u64) -> Self
```
| 参数 | 类型 | 说明 |
|------|------|------|
| `capacity` | `u64` | 桶容量(最大令牌数) |
| `refill_interval_us` | `u64` | 每个令牌的补充间隔(微秒) |
#### `GcraLimiter::with_rate()`
```rust
pub fn with_rate(capacity: u64, requests_per_second: u64) -> Self
```
| 参数 | 类型 | 说明 |
|------|------|------|
| `capacity` | `u64` | 桶容量(最大令牌数) |
| `requests_per_second` | `u64` | 每秒允许的请求数 |
#### `GcraLimiter::check()`
```rust
pub fn check(&self, cost: u64) -> GcraCheckResult
```
返回详细的同步检查结果:
| 字段 | 类型 | 说明 |
|------|------|------|
| `allowed` | `bool` | 是否允许 |
| `remaining` | `u64` | 剩余额度 |
| `retry_after_us` | `u64` | 被拒绝时建议等待的微秒数 |
**示例:**
```rust
use limiteron::limiters::GcraLimiter;
// 容量 10,每秒 100 个请求
let limiter = GcraLimiter::with_rate(10, 100);
let result = limiter.check(1);
if result.allowed {
println!("✅ 允许,剩余: {}", result.remaining);
} else {
println!("❌ 拒绝,需等待 {} 微秒", result.retry_after_us);
}
```
`GcraLimiter` 同样实现了 `Limiter` trait,可通过 `allow(cost).await` 异步消费。
---
### 其他限流算法
| 类型 | 构造 | 所需特性 | 说明 |
|------|------|---------|------|
| `LeakyBucketLimiter` | `new(capacity: u64, leak_rate: u64) -> Result<_>` | 无 | 漏桶水位记账(判定与令牌桶对偶),标准 `Limiter` 接口,快照报告剩余可入桶空间与漏空时间 |
| `SlidingWindowLogLimiter` | `new(max_requests: u64, window: Duration) -> Result<_>` | 无 | 精确滑动窗口日志,无边界突刺;内存随窗口内请求数线性增长(上限 100K 条) |
| `FixedWindowLimiter` | `new(window_size: Duration, max_requests: u64)` | 无 | 固定窗口计数 |
| `ShardedSlidingWindowLimiter` | `new(window_size: Duration, max_requests: u64)` | 无 | 分片滑动窗口,高并发友好 |
| `ConcurrencyLimiter` | `new(max_concurrent: u64)` | 无 | 并发许可控制 |
| `HierarchicalTokenBucket` | `new(root_capacity: u64, root_refill_rate: u64)` | 无 | HTB 分层令牌桶,`allow(class_path: &[&str], cost)` 按分类路径消费 |
| `AdaptiveConcurrencyLimiter` | `new(config: AdaptiveConcurrencyConfig)` | `adaptive-limiting` | AIMD 自适应并发,按延迟/错误率反馈调窗 |
| `QuotaLimiter` | 见 `limiters::quota_limiter` | `quota-control` | 配额型限流器,供宏与 `LimiterManager` 使用 |
### 已弃用导出
> 自 **v0.2.1** 起,`SlidingWindowLimiter` 不再通过 `limiteron::limiters` 平铺导出。推荐使用 `limiteron::limiters::ShardedSlidingWindowLimiter` 替代,提供更好的并发性能。
>
> 仍可通过全路径 `limiteron::limiters::sliding_window::SlidingWindowLimiter` 访问(模块标注 `#[allow(deprecated)]`),但不推荐新代码使用。
---
## 🚪 封禁管理
需要启用 `ban-manager` 特性。模块位于 `limiteron::ban`。
### BanManager
封禁管理器,提供封禁 CRUD、指数退避时长计算与自动解封任务。
#### `BanManager::new()` / `BanManager::builder()`
```rust
pub async fn new() -> Result<Self, LimiteronError> // 默认内存存储
pub fn builder() -> BanManagerBuilder // 链式配置后调用 build().await
```
#### `BanManager::with_dependencies()`
```rust
pub async fn with_dependencies(
storage: Arc<dyn BanStorage>,
config: BanManagerConfig,
) -> Result<Self, LimiteronError>
```
| 参数 | 类型 | 说明 |
|------|------|------|
| `storage` | `Arc<dyn BanStorage>` | 封禁存储后端 |
| `config` | `BanManagerConfig` | 封禁管理器配置(退避参数、自动解封开关等) |
#### `BanManager::create_ban()`
```rust
pub async fn create_ban(
&self,
target: BanTarget,
reason: String,
source: BanSource,
metadata: serde_json::Value,
duration: Option<StdDuration>,
) -> Result<BanDetail, LimiteronError>
```
| 参数 | 类型 | 说明 |
|------|------|------|
| `target` | `BanTarget` | 封禁目标 |
| `reason` | `String` | 封禁原因 |
| `source` | `BanSource` | `BanSource::Auto` 或 `BanSource::Manual { operator }` |
| `metadata` | `serde_json::Value` | 附加元数据 |
| `duration` | `Option<StdDuration>` | 封禁时长;`None` 表示使用指数退避算法自动计算 |
#### `BanManager::is_banned()`
```rust
pub async fn is_banned(&self, target: &BanTarget) -> Result<Option<BanRecord>, LimiteronError>
```
返回 `Some(BanRecord)` 表示被封禁。`BanRecord` 包含 `target`、`ban_times`、`duration`、`banned_at`、`expires_at`、`is_manual`、`reason` 等字段。
**示例:**
```rust
use limiteron::ban::BanTarget;
use std::time::Duration;
let target = BanTarget::Ip("192.168.1.100".to_string());
// 创建封禁
ban_manager.create_ban(
target.clone(),
"恶意请求".to_string(),
limiteron::ban::BanSource::Manual { operator: "admin".to_string() },
serde_json::json!({}),
Some(Duration::from_secs(3600)),
).await?;
// 查询封禁
if let Some(record) = ban_manager.is_banned(&target).await? {
println!("已被封禁: {},到期: {}", record.reason, record.expires_at);
}
```
**其余方法一览:**
| 方法 | 说明 |
|------|------|
| `read_ban(&target)` | 读取封禁详情(`BanDetail`) |
| `update_ban(...)` | 更新封禁记录 |
| `delete_ban(&target, unbanned_by: String)` | 解封(返回是否成功) |
| `list_bans(filter: BanFilter)` | 分页/过滤查询封禁列表 |
| `calculate_ban_duration(ban_times)` | 按退避算法计算封禁时长 |
| `get_config()` / `update_config()` | 读取与更新运行时配置 |
| `stop_auto_unban_task()` | 停止自动解封后台任务(先取消信号优雅排空 5s,超时才 abort) |
| `is_auto_unban_running()` | 自动解封后台任务是否正在运行 |
### BanTarget 与 BanSource
```rust
#[serde(tag = "type", content = "value")]
pub enum BanTarget {
Ip(String),
UserId(String),
Mac(String),
Geo { country_code: String }, // 大写 2 字母 ISO 3166-1 alpha-2
Cidr(String), // IPv4/IPv6 网段,如 "10.0.0.0/8"
}
pub enum BanSource {
Auto,
Manual { operator: String },
}
```
serde 序列化格式:
| 变体 | type 字段 | value 格式 |
|------|----------|-----------|
| `Ip(String)` | `"ip"` | IP 字符串 |
| `UserId(String)` | `"user"` | 用户 ID |
| `Mac(String)` | `"mac"` | MAC 地址 |
| `Geo { country_code }` | `"geo"` | `{"country_code":"CN"}` |
| `Cidr(String)` | `"cidr"` | 网段字符串 |
> **查询语义**:查询目标为 `Ip` 且精确未命中时,按最长前缀匹配网段封禁记录(`BanTarget::contains_ip` / `prefix_len`)。
### BanFileLoader
从 YAML 文件批量加载封禁规则到 `BanManager`,可选支持文件变更热重载。需要 `ban-manager` 特性;热重载需要额外启用 `config-watcher` 特性。
```rust
pub struct BanFileLoader {
path: PathBuf,
// config-watcher 特性下另有监听任务句柄
}
```
**YAML 文件格式:**
```yaml
bans:
- target:
type: ip # ip | user | mac | geo | cidr
value: "192.168.1.1" # geo 时为 {country_code: "CN"}
reason: "恶意请求"
duration_secs: 3600 # 可选,null/省略 = 使用退避算法
```
| 方法 | 签名 | 说明 |
|------|------|------|
| `new` | `pub fn new(path: impl Into<PathBuf>) -> Self` | 创建加载器 |
| `load_once` | `pub async fn load_once(&self, manager: &BanManager) -> Result<LoadResult, LimiteronError>` | 一次性加载;单条失败不中断整体,失败详情在 `LoadResult.errors`;文件读取/解析失败才返回 `Err` |
| `start_watching` | `pub async fn start_watching(&self, manager: BanManager) -> Result<(), LimiteronError>` | 启动热重载(500ms debounce 防止 DoS),需 `config-watcher` |
| `stop_watching` | `pub async fn stop_watching(&self)` | 停止监听;`Drop` 时自动调用 |
```rust
pub struct LoadResult {
pub success_count: usize,
pub failure_count: usize,
pub errors: Vec<BanLoadError>, // 每项含 target_desc 与 error
}
```
> **安全**:内置 YAML 炸弹防护,文件大小上限 2MB,超限返回 `ConfigError`。
---
## 📊 配额控制
需要启用 `quota-control` 特性。模块位于 `limiteron::quota`。
### QuotaController
#### `QuotaController::builder()`
```rust
pub fn builder() -> QuotaControllerBuilder
```
`QuotaControllerBuilder` 提供以下方法:
| 方法 | 说明 |
|------|------|
| `with_storage(storage: Arc<dyn QuotaStorage>)` | 设置配额存储后端 |
| `with_config(config: QuotaConfig)` | 设置配额配置 |
| `build()` | 构建并返回 `Result<QuotaController, LimiteronError>` |
#### `QuotaController::with_dependencies()`
```rust
pub fn with_dependencies(storage: Arc<dyn QuotaStorage>, config: QuotaConfig) -> Self
```
> **注意**:不存在 `new(limit, window_size)` 参数化构造;`QuotaController::new()` 为零参数默认构造(默认内存存储与默认配置)。
#### `QuotaController::consume()`
```rust
pub async fn consume(
&self,
user_id: &str,
resource: &str,
cost: u64,
) -> Result<ConsumeResult, LimiteronError>
```
返回的 `ConsumeResult`:
| 字段 | 类型 | 说明 |
|------|------|------|
| `allowed` | `bool` | 是否允许继续消费 |
| `remaining` | `u64` | 剩余配额 |
| `alert_triggered` | `bool` | 是否触发告警(基于使用率阈值) |
| `usage_percent` | `f64` | 当前使用率百分比(0-100) |
> **注意**:`user_id` / `resource` 不得包含 `:`(存储 key 以 `{user_id}:{resource}` 拼接,含 `:` 会触发防碰撞 `ValidationError`)。
#### `QuotaConfig`
```rust
pub struct QuotaConfig {
pub quota_type: QuotaType, // 配额类型(默认 Count)
pub limit: u64, // 配额上限
pub window_size: u64, // 窗口大小(秒)
pub allow_overdraft: bool, // 是否允许透支
pub overdraft_limit_percent: u8, // 透支上限(配额的百分比 0-100)
pub alert_config: AlertConfig, // 告警配置
}
```
**示例:**
```rust
use limiteron::quota::{QuotaConfig, QuotaController};
let config = QuotaConfig {
limit: 10000,
window_size: 60,
..Default::default()
};
let quota = QuotaController::builder().with_config(config).build()?;
let result = quota.consume("user123", "api_call", 1).await?;
println!("剩余 {},使用率 {:.1}%", result.remaining, result.usage_percent);
```
---
## 🔌 熔断器
需要启用 `circuit-breaker` 特性。模块位于 `limiteron::circuit`。
### CircuitBreaker
```rust
pub fn new(config: CircuitBreakerConfig<E>) -> Self
```
`CircuitBreaker<E = LimiteronError>` 同时实现 `Default`(默认配置,仅默认错误类型实例化)。
> **注意**:`CircuitBreaker` 本身不存在 `new(failure_threshold, timeout_secs)` 参数化签名,也不存在 `with_config()` 方法——自定义配置请构造 `CircuitBreakerConfig` 后传入 `new()`,或使用 `CircuitBreaker::builder()`。(三参构造器在**配置类型**上:`CircuitBreakerConfig::new`,下表。)
#### `CircuitBreakerConfig`
```rust
pub struct CircuitBreakerConfig<E = LimiteronError> {
pub failure_threshold: u64, // 失败阈值(默认 5)
pub success_threshold: u64, // 半开状态恢复所需成功数(默认 3)
pub timeout: Duration, // 打开状态等待时长(默认 30 秒)
pub half_open_max_calls: u64, // 半开状态最大探测调用数(默认 3)
pub half_open_max_duration: Duration, // 半开探针滞留逃逸时长(默认 30 秒)
pub slow_call_duration_threshold: Duration, // 慢调用时长阈值(默认 500ms)
pub slow_call_rate_threshold: f64, // 慢调用率阈值(默认 0.5)
pub error_classifier: Arc<dyn FailureClassifier<E>>, // 错误分类器
}
```
泛型参数 `E` 为被包装调用的错误类型。默认分类器 `DefaultFailureClassifier` 仅实现
`FailureClassifier<LimiteronError>`;自定义错误类型经
`CircuitBreakerConfig::with_error_classifier(Arc<dyn FailureClassifier<E>>)` 构造配置。
#### `CircuitCallError`
熔断拒绝为显式变体(与 sync 版 `SyncCircuitBreaker` 共用同一类型,定义于
`limiteron::error::CircuitCallError`):
- `CircuitCallError::Open`:熔断打开(冷却中或半开探针配额满),闭包未执行;
- `CircuitCallError::Inner(e)`:调用被放行但自身失败,透传原始错误 `e`。
#### 0.3.0 破坏性变更与迁移
本版对齐 async 与 sync 版的拒绝语义,含三个破坏点:
1. `execute` 返回类型 `Result<T, LimiteronError>` → `Result<T, CircuitCallError<E>>`。
旧 `match Err(LimiteronError::LimitError(msg)) | Err(LimiteronError::CircuitBreakerError(msg))`
(熔断拒绝)改为 `Err(CircuitCallError::Open)`;调用自身的失败错误改从
`Err(CircuitCallError::Inner(e))` 取得(不再与拒绝共用错误通道)。
2. 分类器 trait `ErrorClassifier` 改名 `FailureClassifier<E>`:`impl ErrorClassifier for X`
改为 `impl FailureClassifier<LimiteronError> for X`(方法签名不变)。
3. 默认实现 `DefaultErrorClassifier` 改名 `DefaultFailureClassifier`。
**常用方法:**
| 方法 | 说明 |
|------|------|
| `execute(op).await` | 执行操作,返回 `Result<T, CircuitCallError<E>>`(`op` 返回 `Result<T, E>`) |
| `get_state().await` | 查询当前状态(`CircuitState`:Closed / Open / HalfOpen) |
| `config()` | 读取生效配置 |
| `CircuitBreaker::builder()` | 链式构建器(`CircuitBreakerBuilder`),无需先组装配置结构体 |
| `CircuitBreakerConfig::new(failure_threshold: u64, success_threshold: u64, timeout: Duration)` | 三参构造配置(仅覆盖三个核心阈值,其余字段取 `Default`),仅对默认错误类型 `LimiteronError` 可用 |
| `CircuitBreakerConfig::with_error_classifier(classifier: Arc<dyn FailureClassifier<E>>)` | 带自定义分类器构造配置(泛型错误类型入口,其余字段取 `Default`) |
**示例:**
```rust
use limiteron::circuit::{CircuitBreaker, CircuitBreakerConfig};
// 默认配置
let breaker = CircuitBreaker::new(CircuitBreakerConfig::default());
// 等价于 CircuitBreaker::default()
let state = breaker.get_state().await;
println!("当前状态: {:?}", state);
```
---
## 🔁 重试
需要启用 `retry` 特性。模块位于 `limiteron::retry`,与熔断互补:熔断保护下游、重试消化瞬时抖动。
### `RetryPolicy`
字段全部私有,经链式方法配置(`derive(Debug, Clone)`;重试钩子为方法参数而非策略字段,钩子记账状态由调用方闭包自行捕获):
| 方法 | 签名 | 默认值 |
|------|------|--------|
| `new` | `fn new(max_retries: u32, initial_delay: Duration) -> Self` | 其余取 `Default`(factor 2.0 / max_delay 60s / 无抖动) |
| `with_factor` | `fn with_factor(self, factor: f64) -> Self` | 2.0 |
| `with_max_delay` | `fn with_max_delay(self, max_delay: Duration) -> Self` | 60 秒 |
| `with_jitter` | `fn with_jitter(self, jitter: f64) -> Self` | 0.0(值域 0.0–1.0) |
| `with_budget_ratio` | `fn with_budget_ratio(self, ratio: f64) -> Self` | `None`(不启用预算) |
| `max_retries` | `fn max_retries(&self) -> u32` | 3 |
`Default` 配置:`max_retries = 3`、`initial_delay = 500ms`、`factor = 2.0`、`max_delay = 60s`、`jitter = 0.0`、`budget_ratio = None`。
`max_retries` 不含首次调用(0 = 不重试,只执行一次);执行入口对操作最多跑 `max_retries + 1` 次,
第 `n` 次重试前等 `min(initial × factor^(n-1), max_delay)` 并叠加抖动。
`budget_ratio` 是重试次数占「总调用次数」的比例上限,超预算的重试立即放弃(重试风暴防护:
下游故障时重试流量不超过 总请求 × budget_ratio)。
### 执行入口
| 方法 | 签名 | 特性要求 |
|------|------|----------|
| `execute` | `async fn execute<F, Fut, T, E, P>(&self, op: F, is_retryable: P) -> Result<T, E>`,`F: FnMut() -> Fut`、`Fut: Future<Output = Result<T, E>>`、`P: Fn(&E) -> bool` | 无 |
| `execute_notify` | `async fn execute_notify<F, Fut, T, E, P, N>(&self, op: F, is_retryable: P, on_retry: N) -> Result<T, E>`,`N: Fn(u32, &E)` | 无 |
| `execute_with` | `async fn execute_with<F, Fut, T, E, D>(&self, op: F, decide: D) -> Result<T, E>`,`D: Fn(u32, &E) -> RetryDecision` | 无 |
| `execute_with_breaker` | `async fn execute_with_breaker<F, Fut, T, E, P>(&self, breaker: &CircuitBreaker, op: F, is_retryable: P) -> Result<T, E>` | `circuit-breaker` |
语义要点:
- `op` 为每次重试都重新调用的异步操作工厂;返回值为重试耗尽时的最后一次错误,或首个不可重试错误。
- `execute_notify` 的 `on_retry(attempt, err)` 仅对**实际发生**的重试回调(在该次退避等待前,`attempt` 从 1 起);
不可重试错误与重试耗尽不回调,错误经返回值上报。`execute` 即 `execute_notify` 以空钩子的包装。
- `execute_with` **无独立 `is_retryable` 分类器**:能否重试由决策回调全权判定(不可重试错误返回 `Stop`);
循环硬约束(次数/预算)耗尽时分类器不再被咨询,与 `execute` 同口径。
- `execute_with_breaker`:熔断已打开(或进入半开冷却)时只执行一次操作、错误如实返回,
不再向已判故障的下游注入重试流量。
### `RetryDecision`
```rust
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RetryDecision {
RetryAfter(Duration), // 按上游指示的时长等待后重试
Retry, // 按策略默认退避档位等待后重试
Stop, // 立即放弃重试,原样返回触发错误
}
```
- `RetryAfter(d)` 用于错误携带权威等待时间的场景(限流应答的 `Retry-After`、GCRA 结果的
`GcraCheckResult::retry_after_us`(`gcra` 特性)等);与 `Retry` **完全同等记账**重试预算。
- 实际等待直接睡上游指示值——**不加抖动、不封顶 `max_delay`**(封顶会让消费端早于上游指定时刻
重试,违反指示契约:限流应答会再次拒绝并给出同样等待);指示值的合理性由决策回调负责
(例如对 HTTP `Retry-After` 自行设上限);重试次数仍受 `max_retries` 硬封顶,总时长因此有上界。
- 抖动链的 `prev_delay` 按策略自身档位记账(而非上游指示值),decorrelated 抖动的 `prev × 3`
上界始终锚定策略退避序列,不因单次上游指示而塌缩或膨胀。
### `delay_for_attempt`(自由函数)
```rust
pub fn delay_for_attempt(
attempt: u32,
initial: Duration,
factor: f64,
max_delay: Duration,
jitter: f64,
) -> Duration
```
纯函数:`base = initial × factor^(attempt-1)`(`attempt` 从 1 起),叠加比例抖动
`[1, 1+jitter]`(线性同余伪随机,仅用于打散重试尖峰,**非安全用途**),封顶 `max_delay`(封顶为
绝对上限:抖动在封顶前施加,否则抖动会突破 `max_delay`)。供自管重试循环的消费者按 attempt 号
取延迟,与 `RetryPolicy::execute` 的内部退避共用同一公式;`RetryPolicy` 启用 `jitter` 时在其上
另加 decorrelated 约束(`attempt > 1` 时延迟上界同时受前次延迟 × 3 限制)。
**示例:**
```rust
use limiteron::retry::{RetryDecision, RetryPolicy};
use std::time::Duration;
let policy = RetryPolicy::new(3, Duration::from_millis(200))
.with_factor(2.0)
.with_max_delay(Duration::from_secs(5))
.with_jitter(0.2)
.with_budget_ratio(0.1); // 重试流量不超过总请求的 10%
// 上游给出 Retry-After 时按其指示等待,其余错误自行判定能否重试
let result = policy
.execute_with(
|| fetch_upstream(),
|attempt, err| match err {
UpstreamError::RateLimited { retry_after } if attempt < 3 => {
RetryDecision::RetryAfter(Duration::from_secs(retry_after))
}
UpstreamError::Transient(_) => RetryDecision::Retry,
_ => RetryDecision::Stop,
},
)
.await?;
```
> `execute` / `execute_notify` 与 `execute_with` 的选择:错误分类信息有限时用 `is_retryable` 分类器走
> `execute`;需要逐次读取错误携带的等待时长或做 attempt 级判断时用 `execute_with`。
---
## 🎛️ Governor
主控制器,提供端到端的流量控制:标识符提取、规则匹配、决策链级联执行、负缓存与统计。模块位于 `limiteron::governor`。
### 构造方式
```rust
// 零参数构造:默认内存存储,开箱即用
pub async fn new() -> Result<Self, LimiteronError>
// 完整参数构造(按特性追加 metrics/tracer 参数)
pub async fn with_storage(
config: FlowControlConfig,
storage: Arc<dyn Storage>,
ban_storage: Arc<dyn BanStorage>,
#[cfg(feature = "prometheus")] metrics: Option<Arc<Metrics>>,
#[cfg(feature = "telemetry")] tracer: Option<Arc<Tracer>>,
) -> Result<Self, LimiteronError>
// builder 模式(推荐)
pub fn builder() -> GovernorBuilder
```
`GovernorBuilder` 链式方法:
| 方法 | 说明 |
|------|------|
| `with_config(config: FlowControlConfig)` | 注入配置 |
| `with_storage(storage: Arc<dyn Storage>)` | 注入存储后端 |
| `with_ban_storage(ban_storage: Arc<dyn BanStorage>)` | 注入封禁存储 |
| `with_metrics(metrics: Arc<Metrics>)` | 注入指标收集器(`prometheus` 特性) |
| `with_tracer(tracer: Arc<Tracer>)` | 注入追踪器(`telemetry` 特性) |
| `with_audit_logger(logger: Arc<AuditLogger>)` | 注入审计日志器(`audit-log` 特性) |
| `with_shutdown_snapshot_dir(dir)` | 关闭时统计快照落盘目录(JSON;默认不落盘) |
| `with_l1_cache_enabled(enabled: bool)` | 开关 L1 负缓存 |
| `with_l1_cache_config(config: L1CacheConfig)` | 自定义 L1 负缓存(TTL 与容量) |
| `build().await` | 构建 Governor |
> **注记**:`Metrics` 的 Prometheus 导出由 `start_prometheus_server` 提供(`prometheus` 特性);特性未启用时调用返回错误,错误消息文本已随特性更名由 `monitoring feature is disabled` 变为 `prometheus feature is disabled`(变更披露见 [CHANGELOG](CHANGELOG.md) Unreleased 段)。
**示例:**
```rust
use limiteron::Governor;
use limiteron::adapters::StorageFactory;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut factory = StorageFactory::from_dsn("postgresql://localhost/limiteron");
factory.initialize(None).await?;
let storage = factory.create_storage().await?;
let ban_storage = factory.create_ban_storage().await?;
let governor = Governor::builder()
.with_storage(storage)
.with_ban_storage(ban_storage)
.build()
.await?;
Ok(())
}
```
### `Governor::check()`
```rust
pub async fn check(&self, context: &RequestContext) -> Result<Decision, LimiteronError>
```
| 参数 | 类型 | 说明 |
|------|------|------|
| `context` | `&RequestContext` | 请求上下文(位于 `limiteron::matchers`) |
返回 `Decision`:`Allowed(RateLimitMetadata)` / `Rejected(RejectionMetadata)` / `Banned(BanInfo)`。
### 生命周期与健康检测
| 方法 | 签名 | 说明 |
|------|------|------|
| `shutdown` | `pub async fn shutdown(&self) -> Result<(), LimiteronError>` | 优雅关闭:停配置热重载 watcher、取消后台任务令牌、可选统计快照落盘、停止 auto-unban 与审计写入任务、清空 L1 缓存(幂等;连接池随最后 `Arc` 引用释放由底层关闭) |
| `register_config_watcher_token` | `pub fn register_config_watcher_token(&self, token: tokio_util::sync::CancellationToken)` | 注册配置热重载 watcher 令牌(`watch_and_reload` 返回值),shutdown 统一取消 |
| `shutdown_token` | `pub fn shutdown_token(&self) -> &tokio_util::sync::CancellationToken` | 获取关闭令牌引用,供异步任务监听关闭信号 |
| `is_shutdown` | `pub fn is_shutdown(&self) -> bool` | 是否已关闭 |
| `health_check` | `pub async fn health_check(&self) -> Result<(), LimiteronError>` | 执行真实健康检测(存储、封禁存储等依赖) |
| `health_status` | `pub async fn health_status(&self) -> HealthStatus` | 读取最近一次健康检测的状态快照 |
```rust
pub struct HealthStatus {
pub storage_healthy: bool,
pub ban_storage_healthy: bool,
pub cache_healthy: bool, // L1 缓存
pub background_tasks_alive: bool,
}
```
**示例:**
```rust
use tokio_util::sync::CancellationToken;
// shutdown_token() 返回引用,需 clone 后再 move 到异步任务
let token = governor.shutdown_token().clone();
tokio::spawn(async move {
token.cancelled().await;
println!("Governor 正在关闭");
});
// 健康检测
governor.health_check().await?;
let status = governor.health_status().await;
if !status.storage_healthy {
println!("⚠️ 存储不可用");
}
```
---
## 🔍 匹配器
模块位于 `limiteron::matchers`,负责标识符提取与规则匹配。
### Identifier
```rust
pub enum Identifier {
UserId(String),
Ip(String),
Mac(String),
ApiKey(String),
DeviceId(String),
}
```
### RequestContext
请求上下文,字段公开可直接构造,也可经链式方法构建:
```rust
pub struct RequestContext {
pub user_id: Option<String>,
pub ip: Option<String>,
pub mac: Option<String>,
pub device_id: Option<String>,
pub api_key: Option<String>,
pub headers: HashMap<String, String>,
pub path: String,
pub method: String,
pub client_ip: Option<String>,
pub query_params: HashMap<String, String>,
}
impl RequestContext {
pub fn new() -> Self;
pub fn with_header(mut self, key: &str, value: &str) -> Self;
pub fn with_client_ip(mut self, ip: &str) -> Self;
pub fn with_query_param(mut self, key: &str, value: &str) -> Self;
pub fn with_path(mut self, path: &str) -> Self;
pub fn with_method(mut self, method: &str) -> Self;
pub fn get_header(&self, key: &str) -> Option<&String>;
}
```
### 提取器
内置标识符提取器统一实现 `IdentifierExtractor` trait:
| 提取器 | 构造 | 说明 |
|--------|------|------|
| `UserIdExtractor` | `new(header_name, query_param_name, default_user_id)` / `from_header(name)` / `builder()` | 从 HTTP 头或查询参数提取用户 ID |
| `IpExtractor` | `new(header_names: Vec<String>, validate: bool)` / `builder()` | 按优先级从 HTTP 头列表提取 IP,可校验格式并配置可信代理 |
| `MacExtractor` | `new(...)` / `builder()` | MAC 地址提取 |
| `ApiKeyExtractor` | `from_header(name)` 等 | API Key 提取 |
| `DeviceIdExtractor` | `new(...)` / `builder()` | 设备 ID 提取 |
| `CompositeExtractor` | `new(extractors, fallback_to_default)` / `builder()` | 组合多个提取器,依序尝试 |
**示例:**
```rust
use limiteron::matchers::IpExtractor;
// 使用 new 方法创建
let extractor = IpExtractor::new(
vec!["X-Forwarded-For".to_string(), "X-Real-IP".to_string()],
true,
);
// 或使用 builder 模式
let extractor = IpExtractor::builder()
.header_name("X-Forwarded-For")
.header_name("X-Real-IP")
.validate(true)
.build();
```
### 规则匹配
| 类型 | 说明 |
|------|------|
| `RuleMatcher` | 规则匹配引擎(`new(rules: Vec<Rule>)`) |
| `Matcher` | 内置匹配条件(User / Ip 等,见 `limiteron::config::Matcher`) |
| `CustomMatcher` / `CustomMatcherRegistry` | 自定义匹配器 trait 与注册表 |
| `HeaderMatcher` | 内置 Header 匹配器,`HeaderMatchMode` 前缀/相等双模式(`with_match_mode` / `load_config` 的 `match_mode` 字段) |
| `MethodMatcher` | 内置请求方法匹配器,方法名 ASCII 大小写规范化(`new(methods: Vec<String>)`) |
| `TimeWindowMatcher` | 内置时间窗匹配器 |
| `RegexPathMatcher`(`regex-matching`) | 路径正则匹配器,`new(pattern: &str, case_insensitive: bool)` |
| `GeoMatcher`(`geo-matching`) | 地理位置条件匹配 |
| `DeviceMatcher`(`device-matching`) | User-Agent 解析与设备识别 |
---
### Lua 脚本(`lua-script`)
`oxcache_lua` 提供 7 个经 `OxcacheLuaManager` 注册的 Redis Lua 脚本常量(KEYS/ARGV 约定与返回值见 `src/oxcache_lua.rs` 各 const 文档):
| 脚本 | 语义 |
|------|------|
| `SLIDING_WINDOW_SCRIPT` | 滑动窗口(ZSET,每请求计 1) |
| `SLIDING_WINDOW_LOG_SCRIPT` | 滑动窗口日志(cost 加权,伴随账本增量维护,摊还 O(1);max_requests 上限 100K 与进程内同源) |
| `FIXED_WINDOW_SCRIPT` | 固定窗口(String + TTL) |
| `TOKEN_BUCKET_SCRIPT` | 令牌桶(严格余额判定) |
| `BURST_TOKEN_BUCKET_SCRIPT` | 带突发透支令牌桶(借债放行、负余额记账,burst_allowance ≤ capacity,TTL 钳 24h) |
| `QUOTA_CONSUME_SCRIPT` / `QUOTA_RESET_SCRIPT` | 配额消费(含透支)与重置 |
执行入口:`execute_lua_script` / `load_script` + `execute_cached_script`(经 oxcache `eval_lua`/`EVALSHA`)。
---
## 💾 存储后端
模块位于 `limiteron::storage` 与 `limiteron::adapters`。
### 核心 Trait
| Trait | 职责 |
|-------|------|
| `Storage` | 限流数据存储(令牌桶、计数器等 KV 操作) |
| `BanStorage` | 封禁记录存储 |
| `QuotaStorage` | 配额数据存储 |
三者均以 `Arc<dyn Trait>` 形式注入 Governor 与各组件。
### MemoryStorage
内存存储实现,同时实现 `Storage` / `BanStorage` / `QuotaStorage`。始终可用(无需特性门控),适用于单实例开发、测试与快速原型。
```rust
pub fn new() -> Self
pub fn create_storage() -> Arc<dyn Storage> // 便捷构造(替代已移除的 StorageCreate trait)
```
> **注意**:v0.2.1 移除了 `RedisStorage` 与 `redis-storage` 特性,缓存统一经 oxcache 管理(启用 `cache-redis` 特性接入 Redis 缓存后端,`cache-storage` 为其兼容别名)。
**示例:**
```rust
use limiteron::storage::MemoryStorage;
use limiteron::Governor;
let storage = MemoryStorage::create_storage();
let governor = Governor::builder()
.with_storage(storage)
.build()
.await?;
```
### StorageFactory
经 dbnexus 创建持久化存储后端的工厂,需要 `postgres` / `sqlite` / `mysql` 之一(三者互斥)。
```rust
pub struct StorageFactory { /* ... */ }
impl StorageFactory {
pub fn from_dsn(dsn: impl Into<String>) -> Self;
pub async fn initialize(&mut self, config: Option<StorageFactoryConfig>) -> Result<(), StorageError>;
pub async fn create_schema(&self) -> Result<(), StorageError>;
pub async fn create_storage(&self) -> Result<Arc<dyn Storage>, StorageError>;
pub async fn create_ban_storage(&self) -> Result<Arc<dyn BanStorage>, StorageError>;
pub async fn create_quota_storage(&self) -> Result<Arc<dyn QuotaStorage>, StorageError>;
}
```
**示例:**
```rust
use limiteron::adapters::StorageFactory;
let mut factory = StorageFactory::from_dsn("postgresql://localhost/limiteron");
factory.initialize(None).await?;
// 按连接后端自动选择建表方言(PostgreSQL / SQLite;MySQL 不支持自动建表,显性报错)
factory.create_schema().await?;
let storage = factory.create_storage().await?;
```
---
## 🌐 Admin REST API
启用 `admin-api` 特性后,Limiteron 提供 REST 端点管理封禁、配额与状态。除探针端点外,全部要求 `Authorization: Bearer <api_key>` 头部认证(恒定时间比较防止时序攻击;多 key 部署可配置 `api_key_operators` 映射与 admin/viewer 角色矩阵)。
**端点总览:**
| 方法与路径 | 说明 | 认证 |
|-----------|------|------|
| `GET /healthz` / `GET /readyz` | K8s 探针端点 | 免认证 |
| `GET /metrics` | Prometheus 指标 | 免认证 |
| `GET /api/v1/status` | 运行状态 | Bearer |
| `GET /api/v1/status/circuit-breaker` | 熔断器状态 | Bearer |
| `GET /api/v1/introspect` | 规则/决策链/配额/封禁/熔断自省 JSON | Bearer |
| `POST /api/v1/ban` | 创建封禁(需 `ban-manager`) | Bearer |
| `DELETE /api/v1/ban/{target}` | 解除封禁(需 `ban-manager`) | Bearer |
| `PUT /api/v1/quota/{user_id}` | 按 user 重置配额使用量(`new_limit=0`;租户维度配额用 `QuotaController::reset_quota_for_tenant`) | Bearer |
| `POST /api/v1/config` | 原子热更新配置 | Bearer |
| `POST /api/v1/check/batch` | 批量决策检查 | Bearer |
| `POST /api/v1/tokens/prefetch` | 批量令牌预取(`BatchTokenPrefetcher`) | Bearer |
> 管理端点自带按路径、按客户端分桶的限流自保护(分桶内存上限 `RATE_BUCKET_MAX_ENTRIES=10000`)。
**OpenAPI 产物(`openapi` 特性)**:完整契约见入库产物 [`docs/openapi.json`](openapi.json)(OpenAPI 3.0.3,12 条路由与 schema)。产物由内存构建器单一事实来源生成,`tests/openapi_drift.rs` 防漂移守卫保证二者逐字节一致——契约变更时红灯,`UPDATE_OPENAPI=1 cargo test --features openapi --test openapi_drift` 重写后须人工复核 diff。协议无关操作面见 `AdminService` trait(`src/admin/service.rs`):axum handlers 与薄客户端共享同一契约,错误类别到状态码的映射唯一(NotConfigured→503 / Invalid→400 / NotFound→404 / Forbidden→403 / Internal→500)。
**薄客户端(`admin-client` 特性)**:`AdminClient::new(base_url, api_key)` 提供与 `AdminService` 一一对应的类型化方法(`status` / `introspect` / `circuit_breaker_status` / `create_ban` / `delete_ban` / `reset_quota` / `apply_config` / `check_batch` / `healthz`)。hyper http1 每请求新建连接,管理面低频场景适用;**临时验证面**——SDK 生成器(sdforge-R11)落地后由生成的 client 接替。
### 只读管理 Web UI(`admin-ui` 特性)
> ⚠️ **无认证警示**:本 UI 面向「本机/可信内网快照查看」设计,**不提供任何认证**。默认绑定 `127.0.0.1:9091`(仅本机可访问);改为非回环地址会将管理快照(规则、统计、健康、熔断状态)暴露给同网段所有主机——**必须前置带认证的反向代理(并在其上终止 TLS)**。服务启动时对非回环绑定发出 `tracing::warn!` 日志留痕。
```rust
use limiteron::admin::{WebUiConfig, WebUiServer};
let config = WebUiConfig {
host: "127.0.0.1".to_string(), // 默认;非回环须前置反向代理
port: 9091,
};
let server = WebUiServer::new(state, config);
server.start().await?;
```
**机械只读守卫**(`src/admin/web.rs`,新增写端点即红灯):
1. 路由表 `ROUTE_TABLE` 是路径清单的唯一事实来源,Router 由表驱动且仅经 `get()` 注册;
2. 守卫测试对表内全部路径 GET 探测(漏注册红灯)+ 对全部路径发 POST/PUT/DELETE 断言 405;
3. 数据 handler 仅接受 `Arc<dyn ReadOnlySnapshotSource>`——`AdminService` 的只读投影 trait(仅 status/introspect/circuit-breaker 三方法),类型面上不存在写方法。
页面为内嵌单页(无构建链,vanilla HTML+JS),fetch `/snapshot` 与 `/circuit-breaker` 渲染聚合统计、组件健康、规则与决策链、熔断器状态,5s 自动刷新。
### POST /api/v1/ban
创建封禁记录。支持 `ip` / `user` / `mac` / `geo` / `cidr` 五种 target 类型。需要 `ban-manager` 特性。
**请求体:**
```rust
pub struct CreateBanRequest {
pub target: BanTarget, // serde: {"type":"...","value":...}
pub reason: String,
pub operator: Option<String>, // 默认 "admin-api"
pub duration_secs: Option<u64>, // None = 退避算法自动计算
}
```
**响应状态码:**
| 状态码 | 含义 |
|--------|------|
| `201 Created` | 封禁创建成功,返回 `{id, ban_times, expires_at, is_manual}` |
| `400 Bad Request` | JSON 语法错误或 `ValidationError`(如无效 IP、小写国家码) |
| `401 Unauthorized` | 缺少或错误的 `Authorization` 头部 |
| `403 Forbidden` | `AuthorizationError`(授权拒绝) |
| `422 Unprocessable Entity` | JSON 合法但缺少必填字段(如 `reason`) |
| `503 Service Unavailable` | 未配置 ban_manager |
| `500 Internal Server Error` | 其他内部错误 |
**示例:**
```bash
# IP 封禁
curl -X POST http://localhost:8080/api/v1/ban \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{"target":{"type":"ip","value":"192.168.1.100"},"reason":"恶意请求"}'
# Geo 地区封禁
curl -X POST http://localhost:8080/api/v1/ban \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{"target":{"type":"geo","value":{"country_code":"CN"}},"reason":"地区封禁","duration_secs":3600}'
```
**成功响应:**
```json
{
"success": true,
"message": "OK",
"data": {
"id": "ban-uuid",
"ban_times": 1,
"expires_at": 1783290000,
"is_manual": true
}
}
```
### DELETE /api/v1/ban/{target}
解除封禁。通过 `?type=` query 参数显式指定目标类型,未提供时自动推断(合法 IP → `ip`,否则 → `user`)。需要 `ban-manager` 特性。
**Query 参数:**
| 参数 | 值 | 说明 |
|------|-----|------|
| `type` | `ip` / `user` / `mac` / `geo` / `cidr` | 显式指定目标类型,未提供时自动推断 |
**请求体(可选):**
```rust
pub struct UnbanRequest {
pub reason: Option<String>,
pub operator: Option<String>,
}
```
**响应状态码:**
| 状态码 | 含义 |
|--------|------|
| `200 OK` | 解封成功 |
| `400 Bad Request` | 不支持的 `type` 值 |
| `401 Unauthorized` | 缺少或错误的 `Authorization` 头部 |
| `404 Not Found` | 目标未被封禁 |
| `503 Service Unavailable` | 未配置 ban_manager |
| `500 Internal Server Error` | 其他内部错误 |
**示例:**
```bash
# 解封 Geo 目标(必须显式指定 type=geo)
curl -X DELETE "http://localhost:8080/api/v1/ban/CN?type=geo" \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{"reason":"解封","operator":"admin-alice"}'
# 解封 IP(type 可省略,自动推断)
curl -X DELETE "http://localhost:8080/api/v1/ban/192.168.1.100" \
-H "Authorization: Bearer your-api-key"
# 解封 MAC(必须显式指定 type=mac)
curl -X DELETE "http://localhost:8080/api/v1/ban/00:1a:2b:3c:4d:5e?type=mac" \
-H "Authorization: Bearer your-api-key"
```
---
## ⚙️ 配置加载
模块位于 `limiteron::config`。
### `ConfigLoader::load_from_file()`
```rust
pub fn load_from_file<P: AsRef<Path>>(path: P) -> Result<FlowControlConfig, LimiteronError>
```
从 TOML 配置文件加载配置。
### `ConfigLoader::load_from_file_with_env()`
```rust
pub fn load_from_file_with_env<P: AsRef<Path>>(path: P) -> Result<FlowControlConfig, LimiteronError>
```
从 TOML 配置文件加载配置,并支持环境变量覆盖(前缀 `LIMITERON_`)。
| 环境变量 | 覆盖配置项 | 说明 |
|---------|-----------|------|
| `LIMITERON_GLOBAL_STORAGE` | `global.storage` | 存储类型:`memory` / `postgresql` / `redis` |
| `LIMITERON_GLOBAL_CACHE` | `global.cache` | 缓存类型:`memory` / `redis` / `none`(经 oxcache) |
| `LIMITERON_GLOBAL_METRICS` | `global.metrics` | 指标类型:`prometheus` / `statsd` / `none` |
**示例:**
```rust
use limiteron::ConfigLoader;
// 先设置环境变量覆盖
std::env::set_var("LIMITERON_GLOBAL_STORAGE", "postgres");
// 加载配置(环境变量覆盖配置文件中的同名项)
let config = ConfigLoader::load_from_file_with_env("config.toml")?;
```
### 程序化构建
`limiteron::config::ConfigBuilder` 提供程序化构建(`with_storage(StorageType)` / `with_cache(CacheBackend)` / `with_metrics(MetricsBackend)` / `with_trusted_proxies(TrustedProxyConfig)` / `with_rule(closure)` / `build()`)。注意 `build()` 要求至少一条规则,且每条规则必须包含至少一个匹配器与一个限流器,校验失败返回 `Err(String)`。规则构建器 `RuleBuilder` 提供 `id` / `name` / `priority` / `user_matcher` / `ip_matcher` / `token_bucket` / `fixed_window` / `sliding_window` / `concurrency_limit` 等方法。
---
## 🚨 错误处理
### `LimiteronError` 枚举
```rust
pub enum LimiteronError {
ConfigError(String),
StorageError(#[from] StorageError),
LimitError(String),
BanError(String),
CircuitBreakerError(String),
FallbackError(String),
AuditLogError(String),
AuthorizationError(String),
IoError(#[from] std::io::Error),
SerdeError(#[from] serde_json::Error),
YamlError(#[from] serde_yaml_ng::Error),
RateLimitExceeded(String),
QuotaExceeded(String),
ConcurrencyLimitExceeded(String),
Throttled(String), // 宏 throttle 排队超时
ValidationError(String),
LockError(String),
TimeError(String),
DependencyError(String),
ParamMismatch(String),
Other(String),
}
```
类型别名 `pub type LimiteronResult<T> = std::result::Result<T, LimiteronError>;`
### 错误处理模式
```rust
// 模式匹配:区分限流、封禁与其他错误
match limiter.allow(1).await {
Ok(true) => println!("✅ 请求允许"),
Ok(false) => println!("❌ 请求被限流"),
Err(LimiteronError::LimitError(msg)) => {
eprintln!("❌ 限流错误: {}", msg);
}
Err(LimiteronError::BanError(msg)) => {
eprintln!("❌ 封禁错误: {}", msg);
}
Err(e) => {
eprintln!("❌ 错误: {:?}", e);
}
}
```
```rust
// ? 操作符:向上传播
async fn process_request() -> Result<(), LimiteronError> {
let limiter = TokenBucketLimiter::new(10, 1);
limiter.allow(1).await?;
Ok(())
}
```
---
## 📐 类型定义
### Decision
决策结果,位于 `limiteron::error`:
```rust
pub enum Decision {
Allowed(RateLimitMetadata),
Rejected(RejectionMetadata),
Banned(BanInfo),
}
```
| 携带类型 | 字段 | 说明 |
|---------|------|------|
| `RateLimitMetadata` | `limit` / `remaining` / `reset_at` / `retry_after: Option<u64>` / `policy` | 允许决策的限流元数据 |
| `RejectionMetadata` | `reason` / `retry_after` / `limit` / `reset_at` | 拒绝决策的详细信息 |
| `BanInfo` | `reason()` / `banned_until()` / `ban_times()` | 封禁信息(经访问器读取) |
### FlowControlConfig
```rust
pub struct FlowControlConfig {
pub version: String,
pub global: GlobalConfig,
pub rules: Vec<Rule>,
}
pub struct GlobalConfig {
pub storage: StorageType, // Memory / PostgreSQL / Redis
pub cache: CacheBackend, // Memory / Redis / None
pub metrics: MetricsBackend, // Prometheus / Statsd / None
pub trusted_proxies: TrustedProxyConfig, // 可信代理配置
}
pub struct TrustedProxyConfig {
pub enabled: bool, // 是否启用可信代理模式
pub proxies: Vec<String>, // 可信代理 IP 列表(支持 CIDR)
// 另有 X-Forwarded-For 最大跳数限制(默认 10)
}
```
### 其他常用类型
| 类型 | 说明 |
|------|------|
| `LimiteronResult<T>` | `Result<T, LimiteronError>` 别名 |
| `RateLimitSnapshot` | `peek` / `remaining` 返回的标准限流头数据 |
| `ConsumeResult` | 配额消费结果(allowed / remaining / alert_triggered / usage_percent) |
| `LoadResult` | BanFileLoader 加载结果 |
| `CircuitState` | 熔断器状态:Closed / Open / HalfOpen |
| `ChainStats` | 决策链统计(总检查数、节点允许/拒绝数) |
| `HealthStatus` | Governor 健康状态快照 |
| `Identifier` | 标识符枚举(UserId / Ip / Mac / ApiKey / DeviceId) |
---
## 💡 使用示例
### 示例 1:基础限流
```rust
use limiteron::limiters::{Limiter, TokenBucketLimiter};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let limiter = TokenBucketLimiter::new(10, 1);
for i in 0..15 {
match limiter.allow(1).await {
Ok(true) => println!("请求 {} ✅", i),
Ok(false) => println!("请求 {} ❌", i),
Err(e) => println!("请求 {} 错误: {:?}", i, e),
}
}
Ok(())
}
```
### 示例 2:封禁管理
```rust
use limiteron::adapters::StorageFactory;
use limiteron::ban::{BanManager, BanManagerConfig, BanSource, BanTarget};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut factory = StorageFactory::from_dsn("postgresql://localhost/limiteron");
factory.initialize(None).await?;
let ban_storage = factory.create_ban_storage().await?;
let ban_manager = BanManager::with_dependencies(ban_storage, BanManagerConfig::default()).await?;
let ip_target = BanTarget::Ip("192.168.1.100".to_string());
ban_manager.create_ban(
ip_target.clone(),
"恶意请求".to_string(),
BanSource::Manual { operator: "admin".to_string() },
serde_json::json!({"severity": "high"}),
Some(Duration::from_secs(3600)),
).await?;
if let Some(record) = ban_manager.is_banned(&ip_target).await? {
println!("❌ IP 已被封禁: {}", record.reason);
println!("到期时间: {}", record.expires_at);
}
Ok(())
}
```
### 示例 3:Governor 决策
```rust
use limiteron::adapters::StorageFactory;
use limiteron::error::Decision;
use limiteron::matchers::RequestContext;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut factory = StorageFactory::from_dsn("postgresql://localhost/limiteron");
factory.initialize(None).await?;
let storage = factory.create_storage().await?;
let ban_storage = factory.create_ban_storage().await?;
let governor = limiteron::Governor::builder()
.with_storage(storage)
.with_ban_storage(ban_storage)
.build()
.await?;
let context = RequestContext::new()
.with_header("X-User-Id", "user123")
.with_path("/api/v1/users")
.with_method("GET");
let decision = governor.check(&context).await?;
match decision {
Decision::Allowed(meta) => println!("✅ 请求允许,剩余 {}", meta.remaining),
Decision::Rejected(meta) => println!("❌ 请求被拒绝: {}", meta.reason),
Decision::Banned(info) => println!("❌ 请求被封禁: {}", info.reason()),
}
Ok(())
}
```
### 示例 4:声明式宏
```rust
use limiteron::flow_control;
#[flow_control(rate = "100/s", quota = "10000/m", concurrency = 50)]
async fn api_handler(user_id: &str) -> Result<String, limiteron::error::LimiteronError> {
Ok(format!("处理用户 {} 的请求", user_id))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let result = api_handler("user123").await?;
println!("{}", result);
Ok(())
}
```
更多可运行示例见 [examples/](../examples/)(21 个示例覆盖全部核心能力)。
---
[🏠 返回首页](../README.md) • [📖 用户指南](USER_GUIDE.md) • [❓ 常见问题](FAQ.md)