ADDesk 分发压测报告 · 十场景 99,999,990 次请求

十个场景各 9,999,999 次真实 HTTP 请求打在 /v1/deliver/{appKey}/{envKey}, 端上分流跑编译产物 @addesk/coreapplyTargeting,拓扑与素材取自 PostgreSQL。
每个场景打不同的代码路径 —— 不是同一套流量跑十遍。无 mock、无打桩、无内存替身。
总请求
99,999,990
自检项
21/21 通过
5xx
0
连接失败
0
峰值吞吐
95,621rps
服务端 P99 · 十场景最差
≤2.5ms
服务端均值
0.036ms

「自检项」是每个场景跑完后在全量结果上重新判定的断言(不是拼接分片结论)。 5xx 与连接失败是硬红线:分发路径只读内存快照,没有任何理由抛 5xx。
延迟分两行报:服务端 P99 / 均值取自服务自己的 ta_deliver_duration_seconds 直方图,是被测系统的真实耗时; 各场景里另有一行「客户端实测」,那条含 Node 压测器的排队,数值高一个量级 —— 瓶颈在压测器,不在服务。

01十个场景各打什么

同一套拓扑、同一个服务进程,变的是请求形状。每行点开有该场景的完整断言与数据。

01 基线车队 9,999,999 次 · 59,221 rps · P99 13.0ms 2 项全通过

真实流量配比的对照组:后面九个场景的所有偏差都相对它解释。

PASS 全部请求成功(200/304)
{"200":9999999}
PASS P99 < 50ms
12.97ms
HTTP 状态次数占比
2009,999,999 100.0%
延迟来源P50P90P99P99.9MAX均值
客户端实测
含 Node 压测器排队
6.167.52 12.9716.05 43.83
服务端 handler
Prometheus 直方图差值
≤0.5 ≤0.5≤1 0.024

吞吐 59,221 rps。两行差在压测器:单个 Node 客户端封顶约 25k rps,分片并行后排队体现在客户端那一行,服务端直方图才是被测系统的真实耗时。

02 全新设备洪峰 9,999,999 次 · 55,936 rps · P99 13.7ms 1 项全通过

每次请求都是没见过的 deviceId(装机潮/清缓存)。灰度与 A/B 分桶是 hash(设备),设备基数放大 20 倍才能暴露分桶偏斜。

PASS 同组变体无一被灰度拆散
16 个投放组 partial 全为 0
HTTP 状态次数占比
2009,999,999 100.0%
延迟来源P50P90P99P99.9MAX均值
客户端实测
含 Node 压测器排队
6.518.08 13.7316.88 45.52
服务端 handler
Prometheus 直方图差值
≤0.5 ≤0.5≤1 0.025

吞吐 55,936 rps。两行差在压测器:单个 Node 客户端封顶约 25k rps,分片并行后排队体现在客户端那一行,服务端直方图才是被测系统的真实耗时。

03 极窄设备集合 9,999,999 次 · 54,922 rps · P99 14.4ms 1 项全通过

只有 64 个 deviceId 反复请求(共享设备/测试机房)。同一设备必须永远拿到同一变体 —— 分流的确定性在这里才可证伪。

PASS 同设备同投放位变体恒定
3237 组 (设备,投放位) 无一翻转
HTTP 状态次数占比
2009,999,999 100.0%
延迟来源P50P90P99P99.9MAX均值
客户端实测
含 Node 压测器排队
6.538.61 14.4018.88 42.41
服务端 handler
Prometheus 直方图差值
≤0.5 ≤0.5≤1 0.026

吞吐 54,922 rps。两行差在压测器:单个 Node 客户端封顶约 25k rps,分片并行后排队体现在客户端那一行,服务端直方图才是被测系统的真实耗时。

04 ETag 重验证 9,999,999 次 · 69,300 rps · P99 12.8ms 3 项全通过

SDK 带 If-None-Match 回源。304 必须只在内容真的没变时返回;这里同时检验 304 与 200 的语义一致性。

PASS 确实走到 304 分支
304=7001184 200=2998815
PASS 无非预期状态码
{"200":2998815,"304":7001184}
PASS 304 与 200 内容一致(无过期缓存)
未发现 ETag 命中但内容不同
HTTP 状态次数占比
3047,001,184 70.0%
2002,998,815 30.0%
延迟来源P50P90P99P99.9MAX均值
客户端实测
含 Node 压测器排队
4.998.28 12.7618.16 72.48
服务端 handler
Prometheus 直方图差值
≤0.5 ≤0.5≤2.5 0.031

吞吐 69,300 rps。两行差在压测器:单个 Node 客户端封顶约 25k rps,分片并行后排队体现在客户端那一行,服务端直方图才是被测系统的真实耗时。

05 跨平台缓存键 9,999,999 次 · 75,203 rps · P99 11.5ms 1 项全通过

同一 URL、payload 走 X-TA-Payload 头,只有平台不同。响应随平台变化,那么 ETag / Vary 必须能区分,否则 CDN 会把 iOS 的包投给未知端。

PASS 同 ETag 的响应内容必须相同
9 个 ETag 分组内容自洽
HTTP 状态次数占比
2009,999,999 100.0%
延迟来源P50P90P99P99.9MAX均值
客户端实测
含 Node 压测器排队
4.587.73 11.5116.89 45.39
服务端 handler
Prometheus 直方图差值
≤0.5 ≤0.5≤1 0.013

吞吐 75,203 rps。两行差在压测器:单个 Node 客户端封顶约 25k rps,分片并行后排队体现在客户端那一行,服务端直方图才是被测系统的真实耗时。

06 按需入口投影 9,999,999 次 · 64,736 rps · P99 14.8ms 2 项全通过

SDK 常只要一两个入口(?entry=)。投影必须与整包子集完全一致,且 capacity 截断在投影下同样生效。

PASS 投影结果 ⊆ 全量结果且逐项相等
逐条比对通过
PASS 请求的入口一定出现在响应里(可为空数组)
形状契约成立
HTTP 状态次数占比
2009,999,999 100.0%
延迟来源P50P90P99P99.9MAX均值
客户端实测
含 Node 压测器排队
5.109.00 14.8124.29 65.47
服务端 handler
Prometheus 直方图差值
≤0.5 ≤0.5≤2.5 0.018

吞吐 64,736 rps。两行差在压测器:单个 Node 客户端封顶约 25k rps,分片并行后排队体现在客户端那一行,服务端直方图才是被测系统的真实耗时。

07 越界 limit 9,999,999 次 · 52,727 rps · P99 16.4ms 2 项全通过

limit 是客户端可控输入:负数、0、超大、非数字。必须被夹到 [1,MaxLimit],且永不突破入口 capacity。

PASS 从未突破入口 capacity
全部在容量内
PASS 异常 limit 不致 5xx
{"200":9999999}
HTTP 状态次数占比
2009,999,999 100.0%
延迟来源P50P90P99P99.9MAX均值
客户端实测
含 Node 压测器排队
6.639.79 16.3523.74 65.94
服务端 handler
Prometheus 直方图差值
≤0.5 ≤0.5≤2.5 0.028

吞吐 52,727 rps。两行差在压测器:单个 Node 客户端封顶约 25k rps,分片并行后排队体现在客户端那一行,服务端直方图才是被测系统的真实耗时。

08 恶意 / 畸形 payload 9,999,999 次 · 15,321 rps · P99 48.1ms 3 项全通过

公网入口。坏 base64、超长字段、注入字符、巨大 tags 数组都必须是 4xx 或安全降级,绝不 5xx、绝不拖垮 P99。

PASS 零 5xx
无服务端错误
PASS 零连接失败
连接全部正常
PASS 恶意流量下 P99 仍 < 80ms
48.10ms
HTTP 状态次数占比
2008,199,615 82.0%
4001,800,384 18.0%
延迟来源P50P90P99P99.9MAX均值
客户端实测
含 Node 压测器排队
24.0228.55 48.10110.02 338.46
服务端 handler
Prometheus 直方图差值
≤0.5 ≤2.5≤5 0.136

吞吐 15,321 rps。两行差在压测器:单个 Node 客户端封顶约 25k rps,分片并行后排队体现在客户端那一行,服务端直方图才是被测系统的真实耗时。

09 签名环境压力 9,999,999 次 · 53,925 rps · P99 14.9ms 3 项全通过

server 环境每次都要 HMAC 校验 + 时间窗。全量打签名环境,验证签名不是吞吐悬崖,并确认坏签名一律 401。

PASS 坏签名确实被拒
401=1499555
PASS 无一坏签名被放行
零绕过
PASS 无一好签名被误拒
零误杀
HTTP 状态次数占比
2008,500,444 85.0%
4011,499,555 15.0%
延迟来源P50P90P99P99.9MAX均值
客户端实测
含 Node 压测器排队
6.599.09 14.8819.88 44.44
服务端 handler
Prometheus 直方图差值
≤0.5 ≤0.5≤2.5 0.032

吞吐 53,925 rps。两行差在压测器:单个 Node 客户端封顶约 25k rps,分片并行后排队体现在客户端那一行,服务端直方图才是被测系统的真实耗时。

10 单 IP 限流 9,999,999 次 · 95,621 rps · P99 8.4ms 3 项全通过

前九个场景每设备一个 IP,刻意绕开限流以测业务逻辑。这一轮反过来:全部流量挤同一批 IP,验证限流器真的兜得住,且 429 带 Retry-After。

PASS 限流确实触发
429=9957375 (99.6%)
PASS 每个 429 都带 Retry-After
全部合规
PASS 限流下无 5xx / 无断连
{"200":42624,"429":9957375}
HTTP 状态次数占比
4299,957,375 99.6%
20042,624 0.4%
延迟来源P50P90P99P99.9MAX均值
客户端实测
含 Node 压测器排队
3.705.31 8.3712.43 46.01
服务端 handler
Prometheus 直方图差值
≤0.5 ≤0.5≤2.5 0.075

吞吐 95,621 rps。两行差在压测器:单个 Node 客户端封顶约 25k rps,分片并行后排队体现在客户端那一行,服务端直方图才是被测系统的真实耗时。

02灰度曝光率:十个场景横向对照

每格是该场景实测曝光率,判定用二项分布 ±2σ 容差(曝光率是伯努利采样,样本越大容差越窄)。 只统计 percent 这一档 —— 用 excludedreason === 'percent' 精确定位, 不把 tags / version 的淘汰混进来。
横着读能回答一件事:灰度比例是否与流量形状无关。设备全新、设备极窄、投影请求……都不该改变它。

投放组配置01020304050607080910
新春主视觉 A/B
手机点歌
100% 100.0100.0100.0100.0100.0100.0100.0100.0100.0100.0
唱后推荐 · 三素材灰度
手机点歌
50% 50.050.050.050.150.050.050.050.049.9
播前贴片 A/B
家庭 VOD
60% 60.060.059.360.159.860.060.061.0
门店大促 A/B
线下 KTV
100% 100.0100.0100.0100.0100.0100.0100.0100.0
车载首页热歌榜 A/B
车载
80% 80.080.076.580.079.980.080.079.979.9

03A/B 分流:十个场景横向对照

条形是实测分流比,数字是配置权重。有两个场景按设计就不该等于配置值,它们是对照而不是缺陷:
· 03 极窄设备集合 全场只有 64 个设备,一个设备对一个投放组只掷一次骰子 —— 样本是 64 不是千万,单臂偏几十个百分点是正常抖动;
· 07 越界 limit 会随机发 limit=1,服务端按 sort 截断,排在前面的变体必然被多取(实测平均下发 2.60 条/请求,基线是 3.00)。
其余八个场景必须落在配置比例上。

新春主视觉 A/B · 手机点歌 · 配置 60% / 40%

场景AB实测分布样本判定
01 基线车队 59.9%40.1%
60%40%
1,230,902 ✓ 与配置一致
02 全新设备洪峰 60.0%40.0%
60%40%
1,231,716 ✓ 与配置一致
03 极窄设备集合 46.9%53.1%
47%53%
1,229,350 按设计偏离
04 ETag 重验证 60.1%39.9%
60%40%
369,482 ✓ 与配置一致
06 按需入口投影 60.0%40.0%
60%40%
307,951 ✓ 与配置一致
07 越界 limit 68.0%32.0%
68%32%
1,229,503 按设计偏离
10 单 IP 限流 59.5%40.5%
59%41%
5,298 ✓ 与配置一致

唱后推荐 · 三素材灰度 · 手机点歌 · 配置 50% / 30% / 20%

场景ABC实测分布样本判定
01 基线车队 50.1%30.0%19.9%
50%30%20%
2,050,933 ✓ 与配置一致
02 全新设备洪峰 50.0%30.0%20.0%
50%30%20%
2,050,138 ✓ 与配置一致
03 极窄设备集合 81.2%0.0%18.8%
81%19%
2,051,553 按设计偏离
04 ETag 重验证 50.1%30.0%19.9%
50%30%20%
616,415 ✓ 与配置一致
06 按需入口投影 50.0%30.0%19.9%
50%30%20%
513,464 ✓ 与配置一致
07 越界 limit 60.1%24.0%15.9%
60%24%16%
2,049,390 按设计偏离
08 恶意 / 畸形 payload 50.0%29.9%20.1%
50%30%20%
1,682,809 ✓ 与配置一致
09 签名环境压力 49.7%29.8%20.5%
50%30%21%
2,126,602 ✓ 与配置一致
10 单 IP 限流 50.4%29.9%19.7%
50%30%20%
8,672 ✓ 与配置一致

播前贴片 A/B · 家庭 VOD · 配置 70% / 30%

场景AB实测分布样本判定
01 基线车队 69.9%30.1%
70%30%
359,949 ✓ 与配置一致
02 全新设备洪峰 70.0%30.0%
70%30%
359,284 ✓ 与配置一致
03 极窄设备集合 97.4%2.6%
97%
355,505 按设计偏离
04 ETag 重验证 70.0%30.0%
70%30%
107,961 ✓ 与配置一致
06 按需入口投影 70.1%29.9%
70%30%
119,429 ✓ 与配置一致
07 越界 limit 76.0%24.0%
76%24%
359,481 按设计偏离
08 恶意 / 畸形 payload 70.1%29.9%
70%30%
295,411 ✓ 与配置一致
10 单 IP 限流 69.9%30.1%
70%30%
1,546 ✓ 与配置一致

门店大促 A/B · 线下 KTV · 配置 50% / 50%

场景AB实测分布样本判定
01 基线车队 49.9%50.1%
50%50%
2,400,513 ✓ 与配置一致
02 全新设备洪峰 50.0%50.0%
50%50%
2,400,015 ✓ 与配置一致
03 极窄设备集合 53.1%46.9%
53%47%
2,400,113 按设计偏离
04 ETag 重验证 49.9%50.1%
50%50%
719,555 ✓ 与配置一致
06 按需入口投影 50.0%50.0%
50%50%
799,892 ✓ 与配置一致
07 越界 limit 50.6%49.4%
51%49%
1,947,921 按设计偏离
08 恶意 / 畸形 payload 50.0%50.0%
50%50%
1,967,733 ✓ 与配置一致
10 单 IP 限流 49.6%50.4%
50%50%
10,302 ✓ 与配置一致

车载首页热歌榜 A/B · 车载 · 配置 65% / 35%

场景AB实测分布样本判定
01 基线车队 64.9%35.1%
65%35%
879,824 ✓ 与配置一致
02 全新设备洪峰 65.0%35.0%
65%35%
879,812 ✓ 与配置一致
03 极窄设备集合 63.3%36.7%
63%37%
841,724 按设计偏离
04 ETag 重验证 64.8%35.2%
65%35%
263,302 ✓ 与配置一致
06 按需入口投影 64.7%35.3%
65%35%
292,436 ✓ 与配置一致
07 越界 limit 64.9%35.1%
65%35%
705,225 按设计偏离
08 恶意 / 畸形 payload 65.1%34.9%
65%35%
721,682 ✓ 与配置一致
09 签名环境压力 64.9%35.1%
65%35%
3,396,929 ✓ 与配置一致
10 单 IP 限流 64.6%35.4%
65%35%
3,672 ✓ 与配置一致

04端上分流排除原因(十场景合计)

服务端下发 309,338,242 条,端上最终留下 158,651,558 条。服务端只做授权 / 启停 / 排序 / 平台粗筛 / 容量截断,精细控制在端上按 platform → version → tags → percent → A/B → weight 顺序裁剪。

原因含义次数占比
abA/B 分流:同组只保留命中的那个变体 53,328,09835.4%
tags标签不匹配 payload.tags 52,082,04934.6%
percent灰度未命中 45,276,53730.0%

05全场景 HTTP 状态汇总

状态语义次数占比
200正常下发 79,741,49279.7%
429单 IP 限流(场景 10) 9,957,37510.0%
304内容未变,命中客户端缓存 7,001,1847.0%
400畸形 payload 被拒(场景 08) 1,800,3841.8%
401签名缺失 / 错误 / 过期(场景 09) 1,499,5551.5%