为什么用表格而不是一个数字
“这套服能扛多少人”是一个被问得最多、答得最含糊的问题。原因不是没人算,而是每个人心里的口径不同:有人指同时在线,有人指注册用户,有人指单区峰值,有人指压测机器人数量。
容量表的作用,是强制把这些口径拆开写清楚。拆开之后会发现,真正约束系统的往往不是在线人数,而是房间数、消息速率、登录峰值或世界扫描耗时中的某一个。
一、承载指标的口径
| 指标 | 定义 | 采集维度 | 常见误用 |
|---|---|---|---|
| PCU | 周期内同时在线峰值 | 全区/单区/单玩法 | 用日活代替 |
| CCU | 当前同时在线 | 同上 | 与 PCU 混用 |
| 房间数 | 同时存在的对局/副本实例 | 按玩法、按区服 | 只算匹配房间,漏掉自定义房 |
| tick 预算 | 单房间每帧可用时间 | 按房间类型 | 用平均值掩盖长尾 |
| 消息速率 | 每秒进出消息数 | 按协议、按方向 | 只算下行 |
| 登录 QPS | 每秒登录/重连请求 | 按渠道、按区域 | 忽略重连风暴 |
| 广播扇出 | 单条广播触达的连接数 | 按频道/场景 | 按人数估,不看关系图 |
| 存储增长 | 每日新增数据量 | 按表、按保留期 | 只算主库,不算日志与回放 |
每个指标都要写清三件事:峰值口径(1 分钟还是 5 分钟)、统计范围(全区还是单区)、数据来源(监控还是压测)。
二、两种估算方法
2.1 自底向上:从资源推容量
先测出单实例在目标延迟下的处理能力,再乘以实例数,扣除余量。
单实例容量 = min(
CPU 上限 / 单请求 CPU 成本,
内存上限 / 单连接内存成本,
带宽上限 / 单连接带宽成本,
连接数上限
)
集群容量 = 单实例容量 × 可用实例数 × 有效系数
有效系数通常小于 1,因为负载不会完美均匀。它等于“最热分片的负载 / 平均负载”的倒数,必须实测,不能拍脑袋。
2.2 自顶向下:从业务事件推资源
先估业务事件量,再换算成请求与资源。
对局数/秒 = PCU / 平均对局人数 / 平均对局时长 × 2
结算 QPS = 对局数/秒
发奖 QPS = 结算 QPS × 平均奖励条目数
自顶向下的好处是能发现“业务增长 2 倍,某类请求会增长 5 倍”的非线性关系;坏处是每一层系数都可能有误差,必须用自底向上的结果交叉校验。
三、余量结构
余量不是一个百分比,而是“能扛住哪种故障”。建议按下面四层分别写:
| 余量类型 | 要扛住什么 | 典型取值(示例) | 判定方式 |
|---|---|---|---|
| N+1 | 单实例故障 | 至少多 1 个实例 | 杀掉 1 个实例,延迟是否超预算 |
| 故障域余量 | 单可用区/单机架故障 | 可转移容量 ≥ 单故障域负载 | 模拟整区摘除 |
| 活动余量 | 版本更新、活动开场 | 峰值 × 1.3–1.5 | 历史活动峰值回放 |
| 发布余量 | 滚动发布期间的重复容量 | 至少 1 个批次 | 发布演练 |
四层余量不能简单相加。N+1 与故障域余量常常重叠,活动余量与发布余量也可能同时被占用。表格里要写“叠加规则”,否则会把余量重复计算。
四、扩容触发线
| 信号 | 阈值(示例) | 提前量 | 动作 |
|---|---|---|---|
| CPU 持续高于 70% | 5 分钟 | 10 分钟 | 扩容 1 个批次 |
| 房间排队时长 P99 超预算 | 30 秒 | 立即 | 优先扩房间服 |
| 登录排队长度超阈值 | 500 人 | 立即 | 扩容网关 + 限流 |
| 单分片负载偏离均值 30% | 持续 10 分钟 | 15 分钟 | 触发再均衡评估 |
| 内存使用率高于 80% | 5 分钟 | 10 分钟 | 扩容或降级缓存 |
触发线必须和扩容速度匹配。如果扩容需要 90 秒,而触发线只留了 30 秒提前量,这条线就是装饰。
五、三款产品的示例行
以下数字全部是示例值,用于说明表格结构。
| 产品 | 关键指标 | 峰值(示例) | 单实例能力(示例) | 实例数 | 主要瓶颈 |
|---|---|---|---|---|---|
| 《裂隙战场》 | 同时房间数 | 12,000 | 400 房间/节点 | 30 + N+1 | tick 与广播 |
| 《裂隙战场》 | 结算 QPS | 800 | 200/节点 | 4 + N+1 | 数据库写入 |
| 《群岛纪元》 | 在线玩家 | 180,000 | 6,000/节点 | 30 + 故障域余量 | 世界扫描与跨区读 |
| 《群岛纪元》 | 地图分片数 | 256 | 32/节点 | 8 + N+1 | 内存与快照 |
| 《泡泡工坊》 | 开局 QPS | 1,500 | 500/节点 | 3 + N+1 | 房间创建与登录 |
注意《群岛纪元》的约束不是在线人数,而是地图分片的内存与扫描成本;这也是自顶向下估算容易漏掉的部分。
六、填写顺序
- 先定口径:每个指标写清峰值窗口、统计范围、数据来源。
- 再测单实例:在目标延迟下测,不用极限吞吐。
- 算有效系数:用最热分片与均值之比,而不是假设均匀。
- 写余量结构:四层余量分别对应哪种故障,叠加规则是什么。
- 定触发线:与扩容速度对齐,写清提前量。
- 留复算入口:公式、参数、数据来源都要能被别人重算。
七、常见错误
| 错误 | 后果 | 纠正 |
|---|---|---|
| 用日活代替峰值 | 容量严重高估 | 用 PCU 与峰值窗口 |
| 只算平均延迟 | 长尾超时被掩盖 | 看 P99/P999 与超时率 |
| 余量写成一个百分比 | 不知道能扛什么故障 | 按故障类型分层写 |
| 假设负载均匀 | 热分片先崩 | 实测有效系数 |
| 扩容触发线晚于扩容速度 | 触发即已过载 | 按扩容耗时倒推提前量 |
| 不写数据来源 | 无法复算与更新 | 每个数字标注来源与日期 |
八、一页纸模板
产品/区服:____ 版本:____ 日期:____
峰值口径:____ 分钟窗口 统计范围:____ 数据来源:____
关键指标:
PCU/CCU:____ 房间数:____
登录 QPS:____ 结算 QPS:____
消息速率:____ 广播扇出:____
存储日增:____ 保留期:____
单实例能力(目标延迟 ____ ms):
CPU:____ 请求/秒 内存:____ 连接
带宽:____ Mbps 连接数:____
实例数:____ = 业务需求 ____ × 有效系数 ____ + 余量 ____
余量结构:N+1 ____ / 故障域 ____ / 活动 ____ / 发布 ____
扩容触发线:____(提前量 ____ 秒,扩容耗时 ____ 秒)
主要瓶颈:____ 下一次复算:____
容量表不是一次性的文档。每次大版本、每次活动、每次区域扩张之后都应该重算一次;如果表格三个月没更新,它大概率已经和现实脱节了。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。