http.frm.limit
限流 + 过载 shed 中间件(P6-B;per-IP 令牌桶 + max-in-flight 信号量 + 503 Retry-After)
语义登记(v1 口径): 令牌桶 = 显式值状态(LimBkt 值进值出 —— 纯层无全局无可变量,状态由 组合层持有并以值重建下传;进程内注册表(IP → 桶)归组合层,分布式面 列 P8)。补充 = ((now - last) / ivl) * refill,cap 封顶;last 恒以 steps * ivl 整步前进(分数步留余 —— 确定性:同 now 序列恒同判定, 测试面 now 为注入参数,真钟装配归组合层)。消费 = cost(恒 >= 1,组合 层纪律);不足 → 拒 + Retry-After = ceil((cost - tks) * ivl / refill)。
max-in-flight = 值形信号量(lim_acq/lim_rel):acq n+1 <= maxif 才 ok,超即 shed(ok=0,n 不动);rel 下界 0(幂等防负)。释放点 = 组合层 响应写出后(链返回 resp 后组合层 rel —— 链形 fn 内无 post-return 钩子, 如实登记)。
判定序(登记):in-flight 门先于令牌桶(shed 优先于限流 —— 满载时不再 消耗桶令牌,恢复更快);双门皆过 → next。503 响应:Retry-After = 令牌 面取桶算的 retry,shed 面取 1(常量;面区分登记:shed 无时间估计, 取最小礼让值)。body = "lim rejected"(12 字节)。
per-IP 键 = lim_ip_key:FNV 形算术散列(h*131+c,mod 大素数 4294967291 —— 无位运算(§4.5 在案),I64 域乘加模;宽域播种 z64 惯用法,crypto.ct 同式)。组合层以键索引定长桶槽表;冲突面 = 槽表属组合层,本模块只供键。
注入面:Retry-After 值恒出自整数运算自拼(十进制),无请求字节入头。
use 面:零 use 纯模块(同 cors/sechdr —— 多中间件同入口组合各为无共享 叶子,严格树 E5020 规避;助数字位面自拼不导,防菱形)。
pub struct
struct LimCfg
| Field | Type |
|---|---|
ok |
I64 |
err |
I64 |
cap |
I64 |
refil |
I64 |
ivl |
I64 |
maxif |
I64 |
struct LimBkt
| Field | Type |
|---|---|
tks |
I64 |
last |
I64 |
struct LimTake
判定结果:ok = 1 放行(新桶态随出)/ 0 拒(retry = Retry-After ticks;
拒面桶态仍前移补充步 —— 补充与消费正交,如实登记)
| Field | Type |
|---|---|
ok |
I64 |
retry |
I64 |
tks |
I64 |
last |
I64 |
struct LimIf
| Field | Type |
|---|---|
ok |
I64 |
n |
I64 |
pub fn
| Signature | Returns | Description |
|---|---|---|
lim_err_ok() |
I64 |
err 码:0 ok / 1 参数面(cap/refil/ivl/maxif 任一 <= 0;单码登记) |
lim_err_param() |
I64 |
— |
lcfg_ok(c: LimCfg) |
I64 |
— |
lcfg_err(c: LimCfg) |
I64 |
— |
lcfg_cap(c: LimCfg) |
I64 |
— |
lcfg_refil(c: LimCfg) |
I64 |
— |
lcfg_ivl(c: LimCfg) |
I64 |
— |
lcfg_maxif(c: LimCfg) |
I64 |
— |
lim_cfg(cap: I64, refil: I64, ivl: I64, maxif: I64) |
LimCfg |
构造:cap = 桶容量(突发上限),refil = 每 ivl 补充令牌数,ivl = 补充 周期(注入时钟 tick 数),maxif = max-in-flight 上限 |
lb_tks(b: LimBkt) |
I64 |
— |
lb_last(b: LimBkt) |
I64 |
— |
lim_bkt(tks: I64, last: I64) |
LimBkt |
值构造面((h) 纪律:组合层以 getter 取旧桶态 + 本构造面重建,消费方 不直构字面量;状态下传 = 组合层注册表存 LimBkt 值) |
lim_bkt_new(cap: I64, now: I64) |
LimBkt |
新桶:满容量,last = 装配时注入时钟 |
lt_ok(t: LimTake) |
I64 |
— |
lt_retry(t: LimTake) |
I64 |
— |
lt_tks(t: LimTake) |
I64 |
— |
lt_last(t: LimTake) |
I64 |
— |
lim_take(b: LimBkt, c: LimCfg, now: I64, cost: I64) |
LimTake |
— |
lif_ok(x: LimIf) |
I64 |
— |
lif_n(x: LimIf) |
I64 |
— |
lim_acq(n: I64, maxif: I64) |
LimIf |
获取:n+1 <= maxif → ok=1 携新值;满 → ok=0 shed(n 不动) |
lim_rel(n: I64) |
I64 |
释放:下界 0(幂等防负 —— 重复 rel 语义由组合层纪律约束,值面兜底) |
lim_ip_key(ip: Str) |
I64 |
IP → 键(h*131+c mod 4294967291;无位运算,I64 域乘加模,h < 2^39 不越) |
lim_resp_503(retry: I64) |
Str |
503 过载/限流响应(retry = Retry-After 秒;body 12 字节) |