stress: 控制器 v5.1 —— 涓流豁免三级(退段/入段/续砍)+ 软砍护栏 3→8 + SOFT_FLOOR 25→40;dp7 前 1.5h 实测:99% 线下比率陷阱锁死 degraded 砍到 3/min 浏览器饿死,验证码涓流(~14/时)唯一解药是爬坡摊薄(稀释论)
This commit is contained in:
@@ -6,14 +6,15 @@
|
||||
* 双路径原形态(runtime=auto,无 sticky,全池公平负载选号):
|
||||
* GET /api/serp/json/search?q=...&num=10
|
||||
* 令牌内走 go-fetch(全局限流 fetchPerSec),限流外并发走温池浏览器 —— 组合即生产形态。
|
||||
* AIMD 控制器 v5(dp6 全天实测教训驱动;v4 基础上改四点):
|
||||
* AIMD 控制器 v5.1(dp6 全天实测教训驱动;v4 基础上改四点,v5.1 再改三点):
|
||||
* 硬约束(成功率即约束本身):首次跌破 99%(失败≥2)×0.7、<96% ×0.5;退化段内续砍
|
||||
* 需短窗 <96% 且全程增量新失败 ≥2 —— dp5 教训:同一波旧失败被短窗反复引用,
|
||||
* 五分钟连砍五刀 175→30/min,直接打灭浏览器溢出路径;
|
||||
* 软信号按事件段(episode)迟滞 + 绝对数护栏(低速率下 1~2 个噪音 = 高比率,不得触发):
|
||||
* 验证码 10min 窗 ≥3 个且占比>2% ×0.5、≥3 个且>0.5% ×0.7;门壳 ≥3 且占比>15% ×0.85;
|
||||
* 池空>5 ×0.85;软砍下限 SOFT_FLOOR=25 —— 背景验证码供给恒定,速率越低比率越高,
|
||||
* 比率规则在低位永真(dp5 实测 12:00-17:00 自 52/min 自残至 3/min);
|
||||
* 需短窗 <96% 且(非验证码失败 ≥1 或验证码 ≥5/10min)且全程增量新失败 ≥2;
|
||||
* 涓流豁免(v5.1,dp7 前 1.5h 实测:99% 线下比率陷阱锁死 degraded 砍到 3/min):
|
||||
* 30min 窗零非验证码失败且短窗验证码 ≤2 = 涓流 —— 不入段、可退段(短窗 ≥98.5%)、
|
||||
* 验证码涓流的唯一解药是爬坡摊薄(稀释论),砍速让分母变小占比更高;
|
||||
* 软信号按事件段(episode)迟滞 + 绝对数护栏:验证码 10min 窗 ≥8 个(v5.1:5→8,只砍
|
||||
* 波次规模)且占比>2% ×0.5(重波次 ≥12)、≥8 个且>0.5% ×0.7;门壳 ≥3 且占比>15% ×0.85;
|
||||
* 池空>5 ×0.85;软砍下限 SOFT_FLOOR=40(v5.1:25→40,保稀释安全线);
|
||||
* 干净爬坡:不在退化段 且 短窗干净 且 无池空 且(验证码 0 个或样本 ≥300)→ 向「干净
|
||||
* 水位」(30min 窗 ≥99.5% 时的最高速率)以 ×1.3/拍快速回收,水位之上每 5 拍 ×1.08。
|
||||
* v5 修 dp6 实测「低速恢复锁死」:短窗成功率 ≥99.5% 在低速涓流下永不可达
|
||||
@@ -148,8 +149,8 @@ let degraded = false;
|
||||
let failsAtLastCut = 0;
|
||||
/** # 成员变量 干净水位:30min 窗 ≥99.5% 且短窗 ≥99% 时达到过的最高速率(深跌后向水位快速回收;dp5 教训:×1.08/5 拍从 3/min 爬回需 3 小时,温池 150 ready 全程空转) **/
|
||||
let maxCleanRate = 0;
|
||||
/** # 成员变量 软砍速率下限(req/min):背景验证码供给恒定,速率越低比率越高,比率规则在低位永真 → 钉死地板(dp5 实测 12:00-17:00 自 52/min 自残至 3/min)。软规则不砍破此位;真退化由硬规则(无下限)兜底 **/
|
||||
const SOFT_FLOOR = 25;
|
||||
/** # 成员变量 软砍速率下限(req/min):背景验证码供给恒定,速率越低比率越高,比率规则在低位永真 → 钉死地板(dp5 实测 12:00-17:00 自 52/min 自残至 3/min)。软规则不砍破此位;真退化由硬规则(无下限)兜底。v5.1 上调 40:99% 目标下 25/min 时涓流(~14 个/时)占比已达 0.93% 贴线,40/min 摊薄到 0.58% 留出安全余量(稀释论) **/
|
||||
const SOFT_FLOOR = 40;
|
||||
|
||||
/** # 函数
|
||||
* 控制器决策(每 60s 调用):按窗口成功率/内部压力调整速率,返回决策记录或 null。
|
||||
@@ -170,25 +171,31 @@ function controlTick(): Record<string, unknown> | null {
|
||||
const from = rate;
|
||||
let to = from;
|
||||
let reason = "hold";
|
||||
// 硬约束:首次跌破 99% 即砍;段内续砍需「进行中」证据 —— 短窗 <96%(比入段门槛更强的
|
||||
// 活跃失败信号,波尾噪声不算)且全程增量新失败 ≥2(高速率下 2 个新失败转瞬即攒,单靠
|
||||
// 增量计数仍会逐分钟级联,dp5 教训:10:24-10:28 五分钟连砍五刀 175→30/min 打灭浏览器溢出)
|
||||
// 硬约束(v5.1,dp7 前 1.5h 实测教训:99% 线下比率陷阱重现在入段/退段/续砍三级 ——
|
||||
// 低速涓流永远压住 99% 窗口线,degraded 锁死 → 砍到 3/min 浏览器饿死;稀释论:
|
||||
// 验证码涓流的唯一解药是爬坡摊薄,砍速让分母变小占比更高,是毒药):
|
||||
// 涓流豁免 = 30min 窗零非验证码失败 且 短窗验证码 ≤2 个(涓流规模,非波次);
|
||||
// ① 退段:窗口 ≥99%,或涓流豁免且短窗 ≥98.5%;② 入段:涓流不入段;
|
||||
// ③ 段内续砍需真证据:非验证码失败 ≥1(我方故障)或验证码 ≥5/10min(波次规模)
|
||||
const fails = tot - wH.ok;
|
||||
const allFails = totals.sent - totals.ok;
|
||||
const successS = wS.sent > 0 ? wS.ok / wS.sent : 1;
|
||||
if (success >= 0.99) degraded = false;
|
||||
const entry = !degraded && success < 0.99 && fails >= 2;
|
||||
const ongoing = degraded && wS.sent >= 10 && successS < 0.96 && allFails - failsAtLastCut >= 2;
|
||||
const nonCapFails = wH.gate + wH.empty + wH.poolEmpty + wH.httpErr + wH.netErr;
|
||||
const trickle = nonCapFails === 0 && wS.captcha <= 2;
|
||||
if (success >= 0.99 || (trickle && successS >= 0.985)) degraded = false;
|
||||
const entry = !degraded && !trickle && success < 0.99 && fails >= 2;
|
||||
const ongoing = degraded && wS.sent >= 10 && successS < 0.96 && (nonCapFails >= 1 || wS.captcha >= 5) && allFails - failsAtLastCut >= 2;
|
||||
if (entry || ongoing) {
|
||||
degraded = true;
|
||||
failsAtLastCut = allFails;
|
||||
to = success < 0.96 ? from * 0.5 : from * 0.7;
|
||||
reason = `success=${(success * 100).toFixed(1)}%<${success < 0.96 ? 96 : 99}%(失败 ${fails}${entry ? "" : ";短窗<96%+新失败≥2"}) ×${success < 0.96 ? 0.5 : 0.7}`;
|
||||
} else {
|
||||
// 软信号:事件段迟滞 + 绝对数护栏(低速率下 1~2 个噪音即高比率,不得触发;dp5 教训)
|
||||
if (wS.captcha >= 3 && capPctS > 0.005 && !captchaWave) {
|
||||
// 软信号:事件段迟滞 + 绝对数护栏(v5.1:验证码护栏 3→8 个/10min —— 只砍波次规模,
|
||||
// 涓流交给稀释;低速率下 1~2 个噪音即高比率,不得触发;dp5 教训)
|
||||
if (wS.captcha >= 8 && capPctS > 0.005 && !captchaWave) {
|
||||
captchaWave = true;
|
||||
const heavy = wS.captcha >= 5 && capPctS > 0.02;
|
||||
const heavy = wS.captcha >= 12 && capPctS > 0.02;
|
||||
to = Math.max(SOFT_FLOOR, from * (heavy ? 0.5 : 0.7));
|
||||
reason = `验证码 ${wS.captcha} 个占比 ${(capPctS * 100).toFixed(2)}% ${heavy ? "×0.5" : "×0.7"}`;
|
||||
} else if (wS.captcha === 0) captchaWave = false;
|
||||
@@ -206,11 +213,11 @@ function controlTick(): Record<string, unknown> | null {
|
||||
// 干净水位记账:30min 窗 ≥99.5% 且短窗 ≥99% 时的速率即为「实测可行」
|
||||
if (success >= 0.995 && successS >= 0.99 && wS.sent >= 10) maxCleanRate = Math.max(maxCleanRate, from);
|
||||
// 干净爬坡:退化段中不爬(30min 窗未恢复 99%);深跌后向水位快速回收 ×1.3/拍,水位之上 ×1.08/5 拍;
|
||||
// 爬坡验证码条件:主条件短窗成功率 ≥99.5%,备选「验证码 ≤1 且短窗 ≥98.5%」修 dp6 实测
|
||||
// 低速恢复锁死(涓流 1~2 个验证码在低速小分母下永远压住 99.5%,高速率下占比可忽略);
|
||||
// 爬坡验证码条件:主条件短窗成功率 ≥99.5%,备选「验证码 ≤2 且短窗 ≥98%」(v5.1:与涓流
|
||||
// 豁免口径一致,修 dp6 实测低速恢复锁死 + dp7 实测涓流滞留 —— 爬坡摊薄后比率自然回落);
|
||||
// 短窗 0 个验证码恒可爬,或样本 ≥300 时比率已无意义(绝对护栏统一交给软砍规则)
|
||||
if (to === from && !degraded && wS.sent >= 10) {
|
||||
const cleanS = successS >= 0.995 || (wS.captcha <= 1 && successS >= 0.985);
|
||||
const cleanS = successS >= 0.995 || (wS.captcha <= 2 && successS >= 0.98);
|
||||
if (cleanS && gateRatioS < 0.02 && wS.poolEmpty === 0 && (wS.captcha === 0 || wS.sent >= 300)) {
|
||||
rampSeq++;
|
||||
if (maxCleanRate > 0 && from < maxCleanRate * 0.75) {
|
||||
|
||||
Reference in New Issue
Block a user