日均 1.5 亿请求的系统,容量评估到底怎么做
2026/9/16 12:27:55 网站建设 项目流程

做搜索服务的后端同学,面试必被问:“你们日均几亿请求,容量是怎么规划的?”
这题看似算术题,实际考察的是:你有没有真正为生产系统的容量兜过底
本文用一套真实系统的数字,把从日均请求量到机器数、再到线程数的完整推导链走一遍,最后聊聊为什么 P99 比平均 RT 重要、同步和异步模型下线程数为什么差一个数量级。


一、先看流量形态,再谈容量

容量评估的第一步不是套公式,而是搞清楚你的流量长什么样。两种典型画像:

对码服务搜索服务
日均请求5 亿1.5 亿
平均 QPS≈ 5787≈ 1736
峰值 QPS62003800
峰均比1.072.18

平均 QPS = 日均请求量 ÷ 86400。搜索服务:1.5 亿 ÷ 86400 ≈ 1736。

峰均比是流量形态的灵魂

  • 峰均比 1.07 —— 机器般平稳的批处理型流量(上游定时任务批量对码),容量按均值附近规划即可
  • 峰均比 2.18 —— 典型潮汐型业务流量(白天高、夜间低,有明显的早晚高峰),容量必须按峰值规划——按均值备机器,白天必挂

这带来一个矛盾:按峰值备的容量,夜间利用率严重不足(均值只有峰值一半)。所以潮汐型系统的标准解法是K8S HPA 分时伸缩:低峰自动缩容省资源。一道容量算术题,答到这里就变成了架构题。

二、单机容量:一个被大多数人做错的定义

拿到峰值 3800,下一步是算需要多少台机器——但先要回答:单机能扛多少?

这里有个高频踩坑点。很多人压测时盯着 CPU:“CPU 到 70% 了,单机容量就是 800 QPS”。错。

单机容量的正确定义:P99 不超过 SLO 前提下的最大 QPS。

RT 分布是右偏长尾(后面第三节细说),CPU 还没到 70% 时,P99 可能早就超标了。所以压测结论必须写成带边界条件的形式:

单机容量 = 700 QPS @ P99 300ms(SLO:P99 ≤ 300ms)

如果你压测报告里只有一个 QPS 数字没有 RT 边界,这份报告在容量评估上是不能用的。

三、完整推导链:从峰值到机器数

现在把整条链走完(搜索服务,服务级口径——含全部接口 + 定时任务 + 消息消费):

日均 1.5 亿 请求 → 平均 QPS = 1.5亿 / 86400 ≈ 1736 → 峰值 QPS 3800,峰均比 2.18(潮汐型,按峰值规划) → 单机容量 700 QPS @ P99 300ms → 实例数 = 3800 / 700 = 5.43 → 向上取整 6 台 → N+2 冗余 = 8 台 → 限流阈值:总量 ~4500(峰值 × 1.2),单机 ~650(压测值 × 0.93)

三个关键决策点:

① 为什么向上取整后还要 N+2?
6 台只是"刚好扛住峰值"。挂 1 台怎么办?滚动发布时摘掉 1 台怎么办?N+2 的验证:挂 2 台剩 6 × 700 = 4200 ≥ 3800 ✓,同时覆盖了"1 台故障 + 1 台在发布窗口"的叠加场景。最终冗余 1.47 倍——不浪费,也不裸奔。

② 总限流为什么是 4500 而不是 3800?
留 20% 突发余量。限流阈值贴着峰值设,一次正常的流量毛刺就触发拒绝,属于自己吓自己。

③ 单机限流为什么是 650 而不是 700?
限流阈值永远略低于实测容量。这 50 QPS 的差值是给 GC 停顿、重试放大、监控采集开销留的呼吸空间。"略低于"这三个字,就是面试官追问时你和背题选手的分水岭。

四、并发数、线程数:一题看穿线程模型

利特尔法则(Little’s Law):

并发数(在途请求数)≈ QPS × RT

搜索服务峰值:3800 × 0.3s =1140 个在途请求。注意,算到这还只是"水位"——水位是流量决定的,占多少资源是线程模型决定的

经典面试题:10000 QPS、RT 100ms 的接口需要多少线程?

先把 100ms 拆开。IO 密集型服务(搜索、对码都是典型):

RT 100ms = IO 等待 80ms(等 Redis / ES / 向量库)+ CPU 计算 20ms

八成时间在等,两成时间在算。问题变成:等的那 80ms,需不需要占着线程?

同步阻塞模型:需要,线程数 ≈ 水位 = 1000

请求从进来到返回整段占一个线程,包括干等的 80ms。代价:

  • 1000 线程 × 1MB 栈 ≈ 1GB 内存押在"睡觉"上
  • 上下文切换开销随线程数暴涨
  • Tomcat 默认maxThreads=200,1000 并发直接排队甚至拒绝

同步模型的出路只有横向加机器:1000 个在途摊到 8 台,每台 125 个,Tomcat 200 就够了。

异步 IO 模型:不需要,线程数几十个

线程发出 IO 请求后挂起(记个回调就走了),等待期间线程去服务别的请求。线程数只取决于计算总量:

所需核数 ≈ QPS × 单请求 CPU 时间 = 10000 × 2ms = 20 核 线程数 ≈ 核数 × 1~2 = 几十个

一句话总结:同步模型下线程数 = 水位(陪等);异步模型下线程数 = 计算量(不陪等),水位靠连接和回调扛。

用真实系统验算(这一步最值钱)

单机峰值 QPS ≈ 3800 / 8 ≈ 475,P99 300ms:

最坏情况在途请求 ≈ 475 × 0.3 = 143 个 < Tomcat 默认 200

刚好卡在线程池上限以内——如果这套配置在生产稳跑了很久,这就解释了"为什么没出事"。再往下推一层:QPS 涨 2 倍,水位逼近 300,同步模型就得加机器或调大 maxThreads,异步化(WebFlux / Netty)才是根治。把"线程模型 → 容量评估 → 演进路线"串成一条线,就是面试官想听的"理解为什么这么设计"。

五、为什么 P99 比平均 RT 重要

RT 分布右偏长尾,平均值会被 1% 的慢请求拉高,却完全掩盖"有多少请求很慢"。标准答案三段式:

  1. 平均值会说谎——长尾被抹平,看不出慢请求的比例
  2. 慢的那 1% 恰恰是核心业务——搜索/对码场景里,慢请求多是实体识别复杂、向量召回维度高的重请求,不是垃圾流量,是最有价值的用户
  3. P99 是资源风险预警器——同步阻塞模型下,慢请求占住线程不放,吃穿线程池就是雪崩的前兆。所以 SLO 和告警阈值都应该建在 P99 上

我们内部 SLO 就是 P99 432ms 做告警;后来经过缓存与检索链路优化,P99 降低了 22%+——本质是在"降 RT"这条路上挖系统容量(想提高 QPS 只有两条路:降 RT,或者加机器)。

六、总结:容量评估的完整心法

1. 看流量形态:日均 → 平均 QPS → 峰值 → 峰均比(潮汐型按峰值规划,HPA 治夜间浪费) 2. 定单机容量:压测 + P99 边界条件(不是 CPU 打满) 3. 算实例数:峰值 / 单机容量,向上取整,加 N+2 冗余 4. 定限流:总量 = 峰值 × 1.2(放突发),单机略低于压测值(留 GC 余量) 5. 验线程模型:水位 = QPS × RT,对比线程池上限——同步靠加机器,异步靠回调

每一层都有数字、有取舍、有验证。容量评估不是算术题,是"为最坏情况做设计"的工程判断题。


*本文来自一个日均过亿请求的搜索/对码系统的真实容量实践。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询