11.07 压测与容量:IM 上线前如何验证连接、发送和扇出
返回第十一卷 · 测量口径:11.01 · 诊断方法:11.04 · I/O 与网络:11.06
11.07 压测与容量:IM 上线前如何验证连接、发送和扇出
DeepTutor 八节初稿经技术与教学审阅后的静态课程。以下负载、性能、容量、故障和阈值都是虚构纸上设计,没有运行 Go、IM、压测工具、数据库、集群或站点。当前 S2
/v1的正文仍非空且最多 6 UTF-8 B、原始 HTTP 请求正文最多 4096 B、同 ID 重复 409、非成员隐藏 404、200 accepted_in_memory仅表示本进程内存受理;未来 S3/v2的stored_in_teaching_db是提议且仍为 6 B,R9 6→9 B 待审。09.02 当前合同
一、把“能撑住多少用户”改写成业务实验
“IM 要支持一万在线”不足以决定机器数:在线连接可能空闲,群聊也可能在一分钟内触发大量投递。真正的需求应写清谁在做什么、哪一个结果必须在多久内发生、峰值多长、发生故障后仍要保住什么。11.01 已要求写分母与确认点;11.04–11.06 又说明 CPU、池、磁盘、网络和慢设备都可能形成瓶颈。11.07 现在设计隔离环境中的未来实验,用受控负载验证这些推论,而不是靠单机跑出的一个“最大 QPS”宣称生产容量。11.01 业务确认点 · Google SRE:容量规划与负载测试
实验分成两种合同:当前 S2 教学接口若由学习者以后实现,只能验证 /v1 内存受理的 200/400/409/404 和等待;未来 S3/S5 链路才能另验权威持久、B 的设备应用确认、断线补拉。即使发送受理每秒 100 次、P95 很好,也不能由此推出每秒 100 次设备交付。将历史查询、在线通知和离线补拉混成一个“成功率”,同样会使容量结果没有业务含义。07.12 跨系统确认矩阵
| 先固定的字段 | 本章纸上示例 | 对结果的作用 |
|---|---|---|
| 对象 | 连接、入站消息、设备投递任务、历史读取分别计 | 避免把连接数当消息吞吐 |
| 成功点 | S2 A 收到内存受理;未来 S5 B 应用确认另计 | 避免只看 HTTP 200 |
| 人群与内容 | 虚构 u-a/u-b/c-a/m-9,固定群规模与正文 6 B 合同 | 防止敏感数据进入实验 |
| 负载形状 | 基线、阶梯、峰值、长稳、撤载恢复 | 防止短峰通过冒充长期安全 |
| 停止门 | 超时/拒绝、积压、内存、生成器异常触发撤载 | 实验不能扩大成无控故障 |
二、从连接、活跃比推到设备任务
设未来教学链路想评审一个纯纸上容量问题:某网关有 10,000 条在线连接,其中 2% 的用户在这一时间窗活跃,即 10,000×0.02=200 个活跃者;每位活跃者平均每秒发 0.1 条入站消息,入站速率为 200×0.1=20 条消息/秒。这里把一条连接暂简化为一个用户;真实多设备时连接与用户不是一对一,必须重新拆分。04.05 长连接生命周期
若把这 20 条全当成未来群消息,假设每条恰好面向 50 位目标成员,每位目标成员有 2 台目标设备,且所有目标都生成独立任务、没有在线过滤/合并/去重,设备任务速率是 20×50×2=2,000 项/秒。这是条件计算值,不是生产上界或已测吞吐;若有单聊、离线设备、静默策略或重试,结果会不同。入站消息、权威记录、broker 事件、设备任务和设备 ACK 应分别计数,不能把 2,000 项叫“2,000 条新消息”。07.06 消息抽象
再给一个单项资源估算:假设每条连接平均占用 32 KiB 进程内存,10,000×32 KiB=312.5 MiB。它只是按连接均摊的纸上量级,未包含用户态队列、goroutine 栈、TLS、内核 socket 缓冲、共享缓存、数据库/网关其他状态和峰值;更不能由此声称“网关只需 313 MiB”。未来试验应分别观测 RSS、Go 管理内存、内核/容器内存及连接状态,不能把 11.05 的 Go 堆曲线当作全部连接成本。11.05 RSS 边界
单变量改变才好解释。 一次先固定连接数与群规模,仅改变活跃比或入站速率;另一次固定入站速率,改变 50 人群到 500 人群;再单独改变每人设备数。若同时把连接、群和正文大小全翻倍,即使吞吐下降也难判断是哪条资源链先饱和。11.04 工作负载画像
三、闭环客户端会在系统变慢时自行减载
闭环负载让一个虚拟用户完成一次操作后才发下一次;开环负载按预设时间计划发起操作,不以之前的响应完成作为下一次计划时间。两者都可能代表真实用户场景,但回答不同问题。Grafana k6 文档分别用固定虚拟用户数和固定到达率解释这些模型;本章只借概念,不运行 k6。k6:开环与闭环
纸上有 10 个虚拟用户、无思考时间,每人一次操作完成后立即发下一次。若每次平均耗时 100 ms,在简化稳定条件下每位约 10 次/秒、合计约 100 次/秒;若系统慢到 1 秒,每位约 1 次/秒、合计约 10 次/秒。数字还忽略了脚本/网络开销,只为显示反馈:被测系统慢 → 闭环客户端发得更少 → 压力自动减轻。如果只报告“高负载测试 P95 还行”,却不报告实际到达率,可能是负载生成器已经停止施压。
开环计划可写“每 100 ms 发起一次”,并分别记录:planned 计划、started 实际开始、dropped 计划但未开始、completed 已有结果、timed_out 超时、inflight 仍在途。开环也不神奇:若生成器 CPU、内存、网络或可用虚拟用户不足,计划不能完全执行;k6 的到达率模型会记录未能启动的 iteration。不能把 dropped 偷算成被测服务成功,也不能无证据全归责于服务。k6:到达率与 VU · k6:dropped iterations
四、协调遗漏:慢的那段时间为何没有样本
协调遗漏是测量过程随系统变慢而减少或错过本应发生的观测,使报告比用户真实等待更乐观。假设原计划在 t=0,100,...,900 ms 各发一次,共 10 次机会。闭环脚本在 t=0 发第一条后被阻塞 1 秒,直到 t=1000 才能发下一条;在原定的 1 秒窗口里,它只记录了一条 1 秒样本,其余 9 个计划机会没有按时发出。不能仅拿这一条的分位数推断“10 次用户机会都只需 1 秒”,更不能把缺失的 9 次当成功。HdrHistogram:协调遗漏处理 · k6:开闭环到达
开环生成器若真的在每个计划点尝试发起,会暴露排队、失败或未能启动的数量;但即使使用开环,也仍需记录计划时间、实际开始时间和结果时间。生成器缺虚拟用户而 dropped 时,我们不知道这些未启动操作若执行会经历怎样的服务时延;不能事后随便填成 0 ms、1 秒或超时。HdrHistogram 有按预期采样间隔作协调遗漏修正的能力,修正是模型推断,不是原本未发请求的真实观测,因此原始计划/实际/缺失计数仍要保存。
时延分布还可能只收集“已完成的 200”。若最慢的 100 次还在途、或被 429/503/断线拒绝,完成者 P95 反而下降。报告必须把分母、超时/拒绝、未完成以及按响应类别拆分的时延放在同一张表;S2 的预期 400/409/404 不应混为服务故障,但也不能为了好看从用户尝试数中消失。11.02 分布与缺失
五、从烟雾检查到阶梯、长稳与恢复
下面是未来隔离实验的设计样例,速率是纸上目标,不是性能结果或推荐线上阈值。运行前须先定义 S2 的业务合同正反例、未来 S3/S5 若存在时的各自确认点、生成器能力、负载数据和停止门。
| 阶段 | 计划负载示意 | 观察重点 | 不能直接宣称 |
|---|---|---|---|
| 烟雾检查 | 少量单连接/单消息 | 6 B、409、404、200 与脱敏日志 | 性能容量已达标 |
| 基线 | 20 入站消息/秒 | 同版本、同数据集的正常分布与资源 | 后续 80/s 一定安全 |
| 阶梯 | 40 → 60 消息/秒,各阶段等状态可比较 | 实际发起/完成、队列趋势、尾延迟、错误 | 只看最后一次快照即可定容量 |
| 短峰 | 80 消息/秒,限定窗口 | 突发承载、拒绝与恢复 | 长期稳态仍可保持 |
| 长稳 | 60 消息/秒,较长观察窗 | RSS/连接/队列是否持续爬升、数据是否可恢复 | 一次 30 分钟可证明永久无泄漏 |
| 撤载恢复 | 回到基线或停发 | backlog 清空速度、旧消息补拉、资源回落 | 撤载后 CPU 低就表示全量已交付 |
每阶段都记录版本、配置、机器、容器限额、客户端/生成器数、连接/活跃比、单聊/群聊与设备分布、消息字节数、数据集、持续时长和采样方法。观察用户结果(当前 A 收到 S2 200,未来另看 B ACK)、入口计划/实际速率、拒绝/超时/仍在途、P50/P95/P99、队列、CPU、Go 分配/GC、磁盘/池、网络重传与生成器自身资源。只有同工作量、同确认点和同采样口径的基线/候选才可比较。11.03 指标与采样
短峰测试、长稳测试和撤载恢复各有独立目的。能承受 80/s 十秒,不代表在 60/s 维持三十分钟时队列不涨,也不代表一分钟断线后恢复不会触发重连风暴;反过来只测稳定 20/s,也不会看到排队拐点。Google SRE 将负载测试与容量及过载失效方式结合讨论;课程中的阶段仍需由实际业务风险选择。Google SRE:级联故障与负载测试
六、容量余量:单实例极限不等于故障后容量
假设未来隔离实验真的在特定消息/群/连接组合下证明:一个实例能长期、同合同地稳定处理 100 条入站消息/秒。这是严格限定的纸上条件容量,不是 OpenIM 或本项目的实测。若目标峰值为 150 条/秒,三实例总名义容量 3×100=300/s;失去一个实例后名义容量 2×100=200/s,比目标多 50/s。若只有两实例,失去一个后只剩 100/s < 150/s,即使平常两实例合计 200/s,也不满足该 N−1 纸上条件。
这道算术仍不足以承诺“三实例一定安全”:单个热点群可能集中在一个分区,网关连接不能瞬时均匀迁移,数据库或 broker 可能是共享瓶颈,节点故障时重连与重试会使到达率高于原先 150/s。还需分别验证群扇出、设备任务、历史查询、网络出口、存储/队列和恢复窗口的容量;把每实例 100/s 线性相加,只有在分片与共享依赖等前提成立时才有意义。08.05 分区与再平衡 · 11.06 慢消费者
“余量”至少写明对什么资源、哪种工作量、哪段故障和多久。200−150=50/s 是该模型在单节点失效后的名义消息吞吐余量,不是连接内存、数据库 IOPS、离线补拉或设备 ACK 的余量。若业务一周后把群平均目标从 50 改成 500,同样的 150 条入站消息/秒可能产生十倍设备任务,原容量结论需要重新试验。Google SRE:容量规划
七、停止门、证据包与公开项目边界
压测只应在可控、隔离、拥有权限的环境中,用虚构账号、消息和会话;实验任务不能向真实用户发送内容。开始前写出撤载/停止条件:如未启动计划请求持续上升、服务端超时或拒绝超过本次实验门、队列无界增长、内存逼近环境限额、历史补拉对账失败或生成器本身饱和。门槛值应由学习者的资源预算和实验目的预先设定,本章不凭空给生产 SLO。触发后停止增压,保留证据,先恢复与对账再分析。11.04 诊断闭环
可复核的实验包至少含:版本与提交、测试合同、生成器脚本/配置、虚构数据生成方式、计划与实际到达、客户端/服务/设备分层指标、原始窗口与样本量、环境资源、停止事件、结果和未验证风险。写“100/s 稳定”必须指明持续多久、成功点是什么、错/超时/积压与机器范围如何。实验若未运行,应只提交设计与待测项,不能填伪造的通过值。10.09 CI 与制品身份
固定 openimsdk/open-im-server 提交 f6411a8a1a31d3df36f4c2b3ad28481a94141e1f 的 send.go 选定分支调用 MsgToMQ 后返回;另一 Mongo 消费路径调用 BatchInsertChat2DB。这两段只提示发送与消费分属异步阶段,不能推出 OpenIM 的真实吞吐、P95、设备任务倍数、部署副本数或故障后余量。公开项目若要实测,必须另外固定环境、负载和授权,不将本章纸上数值贴为上游结果。OpenIM 阅读地图
八、22 道分层练习:评审一份容量试验设计
先独立写公式与分母,再看反馈;后六题要求说明改动对用户结果的影响。
基础 1–8:定义负载和确认点
1. 一万在线连接能直接表示一万条消息/秒吗?
不能。还需活跃比、每活跃者发送率、会话类型与突发形状。
2. 当前 S2 的 200 能作为未来设备送达压测成功点吗?
不能。它只代表进程内存受理;设备应用 ACK 要另定义。
3. 10,000 连接中 2% 活跃,是多少活跃者?
按本题一连接一人的简化假设为 10,000×0.02=200 人。
4. 每活跃者 0.1 条/秒,入站约多少条/秒?
200×0.1=20 条/秒。
5. 入站 20/s、每条恰好面向 50 人且每人 2 设备,本题条件下任务速率多少?
在本题无过滤/合并/重试假设下是 20×50×2=2,000 个设备任务/秒,不是生产上界或 2,000 条权威消息。
6. 10,000 连接各假设 32 KiB,共约多少 MiB?
10,000×32/1024=312.5 MiB,未计其他内存。
7. 闭环客户端何时开始下一次操作?
上一次按脚本完成后才开始;系统变慢会降低实际到达率。
8. 开环计划率等于实际启动率吗?
不一定。生成器资源/VU 不足或其他限制会使计划操作未启动。
推导 9–16:遗漏、阶段与余量
9. 10 个闭环 VU 无思考时间、每次 100 ms,简化速率约多少?
约 10/0.1=100 次/秒,忽略脚本与网络开销。
10. 若每次变成 1 秒,简化速率约多少?
约 10/1=10 次/秒;这是系统变慢时闭环自行减载。
11. 每 100 ms 计划一次共 10 次,首个闭环请求阻塞 1 秒,窗口里少了几次计划机会?
相对固定计划的 10 次,有 9 次未按时发出;只看到一条 1 秒样本。
12. `dropped_iterations` 可算作被测服务成功或失败吗?
不能直接算。它表示计划操作未启动,须先查生成器/VU 配置和服务变慢的影响。
13. 只给收到 200 的请求算 P95,有什么盲区?
超时、拒绝和仍在途被排除,最慢体验可能消失;需同窗并报数量。
14. 80/s 短峰通过能证明 60/s 长稳安全吗?
不能。长稳还要观察队列、内存、连接与恢复是否持续恶化。
15. 每实例纸上稳定 100/s,三实例失一后名义容量多少?
2×100=200/s;目标 150/s 时名义余量 50/s。
16. 同条件只有两实例,失一后可守 150/s 吗?
不能。只剩 100/s,小于目标 150/s。
决策 17–22:业务结果与停止门
17. 三实例 N−1 算式通过就能宣称线上安全?
不能。热点分区、连接迁移、共享数据库/队列和重连风暴仍需验证。
18. 群规模从 50 增到 500,原入站 150/s 容量结论可直接沿用吗?
不能。设备任务可能约十倍,须重测扇出和下游容量。
19. 压测达到停止门后应继续增压确认极限吗?
不应。先撤载、保存证据、恢复和对账,再决定下一次有边界的实验。
20. 只记录服务端 CPU 和平均时延,能复核实验吗?
不能。还需版本、负载模型、计划/实际到达、样本分布、拒绝/超时/积压及生成器状态。
21. 固定 OpenIM 两处源码能证明每实例 100/s 或 2,000 设备任务/s?
不能。它们只提示异步边界,没有实际负载或性能测量。
22. 交付一份可审容量实验计划至少包含什么?
业务目标与确认点、工作量维度、开闭环和缺失计数、阶段/停门、资源与用户结果、N−1 假设、脚本/环境/版本及残余风险。
本章完成标准与后续路径
能从连接、活跃比和群设备数算出不同单位的压力;说明闭环自行减载、开环仍会有未启动计划以及协调遗漏;写出阶梯、长稳、撤载恢复的观察与停门;手算 N−1 名义余量并指出热点/共享依赖反例,才算完成第一轮。本章只交实验设计,实际性能结果须由学习者在隔离环境另采。下一章11.08 SLO 与告警将把明确的用户确认点转成 SLI、目标、错误预算和可行动告警。