2 个版本
0.0.2 | 2024 年 5 月 30 日 |
---|---|
0.0.1 | 2024 年 5 月 25 日 |
#2 in #throttling
每月 64 次下载
38KB
642 行
尼娜
尼娜 是一个使用比例-积分-微分(PID)控制器的适应性速率限制器。该项目包含两个主要组件
- 尼娜:一个用于适应性速率限制的 Rust crate。
- 尼娜哨兵:一个独立的速率限制 gRPC 服务,旨在作为现有服务的边车运行。
概述
尼娜
尼娜是一个 Rust crate,它使用 PID 控制器提供适应性速率限制功能。该 crate 旨在提供一种动态高效的方式来管理请求数率,使其适用于高吞吐量服务。
功能
- PID 控制器:使用高度可配置的比例-积分-微分(PID)控制器,根据当前流量模式动态调整速率限制
- 可配置的滑动窗口:使用可配置的滑动窗口确定每秒事务数(TPS),确保准确的速率限制决策
- 配置:允许微调 PID 参数(
kp
、ki
、kd
)、错误限制、输出限制和更新间隔
尼娜哨兵(进行中)
尼娜哨兵是一个独立的速率限制服务,将支持 gRPC,以便作为微服务架构中的边车轻松集成。
入门
要开始使用尼娜,将其添加到您的 Cargo.toml 中
[dependencies]
nenya = "0.0.2"
示例
具有静态设置点的基本速率限制器
use nenya::RateLimiterBuilder;
use nenya::pid_controller::PIDControllerBuilder;
use std::time::Duration;
fn main() {
// Create a rate limiter
let mut rate_limiter = RateLimiterBuilder::new(10.0)
.update_interval(Duration::from_secs(1))
.build();
// Simulate request processing and check if throttling is necessary
for _ in 0..20 {
if rate_limiter.should_throttle() {
println!("Request throttled");
} else {
println!("Request accepted");
}
}
}
使用 PID 控制器的动态速率限制器
use nenya::RateLimiterBuilder;
use nenya::pid_controller::PIDControllerBuilder;
use std::time::Duration;
fn main() {
// Create a PID controller with specific parameters
let pid_controller = PIDControllerBuilder::new(10.0)
.kp(1.0)
.ki(0.1)
.kd(0.01)
.build();
// Create a rate limiter using the PID Controller
let mut rate_limiter = RateLimiterBuilder::new(10.0)
.min_rate(5.0)
.max_rate(15.0)
.pid_controller(pid_controller)
.update_interval(Duration::from_secs(1))
.build();
// Simulate request processing and check if throttling is necessary
for _ in 0..20 {
if rate_limiter.should_throttle() {
println!("Request throttled");
} else {
println!("Request accepted");
}
}
}
请求模拟器
尼娜包括一个请求模拟示例,用于测试和调整。您可以使用以下命令运行模拟
cargo run --example request_simulator_plot -- \
--target_tps 80.0 \
--min_tps 75.0 \
--max_tps 100.0 \
--trailing_window 1 \
--duration 120 \
--base_tps 80.0 \
--amplitudes 20.0,7.0,10.0 \
--frequencies 0.05,2.8,4.0 \
--kp 0.8 \
--ki 0.05 \
--kd 0.04 \
--error_limit 10.0 \
--output_limit 3.0 \
--update_interval 500 \
--error_bias 0.0
大多数这些参数都有合理的默认值,可以省略。有关更多详细信息,请参阅
cargo run --example request_simulator_plot -- --help
适应性速率限制
速率限制器通过使用比例-积分-微分(PID)控制器实现适应性速率限制,该控制器根据请求速率确定目标速率限制。此实现包括误差偏差、累积误差夹断、反饱和反馈和输出夹断。
概述
- 错误计算:误差是通过从设置点减去请求速率来计算的。
- 比例项:比例项是比例增益和误差的乘积。
- 误差偏差:误差通过偏差因子进行调整,如果 $B > 0$ 则对正误差反应更强烈,如果 $B < 0$ 则对负误差反应更强烈。
- 积分项:积分项是随时间累积的错误,通过钳位来防止积分饱和。
- 微分项:微分项是误差变化的速率。
- 原始校正:原始校正是指P、I和D项的总和。
- 输出钳位:输出被钳位到一个指定的限制,以防止过度的校正。
- 抗饱和反馈:如果发生钳位,累积错误会被调整以防止积分饱和。
- 最终输出:钳位校正是PID控制器的最终输出。
- 请求限制调整:钳位校正被添加到当前请求限制中,以推导出新的请求限制。
1. 错误计算
误差 $e(t)$ 是通过设定点 $S$ 和请求率 $r(t)$ 的差值来计算的
e(t) = S - r(t)
2. 比例项 (P)
比例项 $P(t)$ 是使用比例增益 $K_p$ 计算的
P(t) = K_p \cdot e(t)
3. 错误偏置
通过偏置 $B$ 调整错误,以更积极地响应正负误差
\text{biased\_error}(t) =
\begin{cases}
e(t) \cdot (1 + B) & \text{if } e(t) > 0 \\
e(t) \cdot (1 - B) & \text{if } e(t) \leq 0
\end{cases}
4. 积分项 (I)
累积误差 $E(t)$ 被钳位以防止积分饱和
E(t) = \text{clamp}\left( E(t-1) + \text{biased\_error}(t), -L, L \right)
其中 $L$ 是误差限制。
积分项 $I(t)$ 然后是
I(t) = K_i \cdot E(t)
5. 微分项 (D)
微分项 $D(t)$ 是使用微分增益 $K_d$ 和误差变化率来计算的
D(t) = K_d \cdot \frac{d e(t)}{dt}
对于离散的时间步长,这可以近似为
D(t) = K_d \cdot \left( e(t) - e(t-1) \right)
6. 原始校正
原始校正 $u(t)$ 是比例、积分和微分项的总和
u(t) = P(t) + I(t) + D(t)
7. 输出钳位
输出校正被钳位以防止过度的输出
u_{\text{clamped}}(t) = \text{clamp}(u(t), -M, M)
其中 $M$ 是输出限制。
8. 抗饱和反馈
如果校正被钳位,累积误差 $E(t)$ 被调整以防止积分饱和
\text{if } u(t) \neq u_{\text{clamped}}(t) \text{ then } E(t) = E(t) - \frac{u(t) - u_{\text{clamped}}(t)}{K_i}
9. 最终输出
PID控制器的最终输出是
u_{\text{clamped}}(t)
10. 请求限制调整
输出被添加到当前请求限制 $R(t-1)$ 中,以推导出新的请求限制 $R(t)$
R(t) = R(t-1) + u_{\text{clamped}}(t)
许可证
本项目受MIT许可证许可。有关详细信息,请参阅LICENSE 文件。
依赖关系
~240KB