想象你是一家网红餐厅的老板。周末晚上,门口排着长长的队伍,客人络绎不绝。你最关心的指标是什么?不是“今天来了多少客人”(那是总客流量),而是“一秒钟内有多少位客人成功入座点餐”——这才是餐厅真正的“瞬时接客能力”。如果这个数字太低,说明餐厅内部某个环节卡住了:可能是厨师出菜太慢,可能是服务员顾不过来,也可能是收银台排起了长队。 AI 推理服务就像这家餐厅。QPS(Queries Per Second,每秒查询数)就是衡量 AI 服务“一秒能接待多少请求”的核心指标。它不像总调用量那样是一个“积累量”,而是一个“瞬时速度”。就像汽车仪表盘上的时速表,你能随时看到当前是 60 码还是 120 码。QPS 监控,就是给 AI 服务装上这块速度表——它能告诉你系统现在是“畅通无阻”还是“堵死瘫痪”,是“刚刚好”还是“资源浪费”。 这篇文章将用“餐厅经营”这条主线贯穿始终,带你从零理解 QPS 监控:从基本定义、测量指标、影响因素,到瓶颈定位、优化策略,再到生产环境中的容量规划和告警,让你不仅能看懂 QPS 曲线,还能像经营餐厅一样,把 AI 服务的“接客效率”调到最佳状态。
QPS 监控是 AI 工程化落地中衡量推理服务健康度的“体检报告”。掌握它,你就具备了定位系统瓶颈、规划算力资源、保障服务稳定性的核心能力,是从“能调模型”到“能上线扛流量”的关键一跃。
可视化演示
展示QPS流量曲线、Little定律延迟关联及弹性伸缩告警策略的三模态交互动画。
本节配有交互动效(进入视口后自动加载,约 3KB)。
QPS流量曲线监控 实际 阈值 QPS=req/time_window 每秒查询数监控流量曲线实时采集请求计数滑动窗口计算QPS值
QPS 基本概念
想象餐厅门口的迎宾员手里有一个计数器。每当一位客人成功入座,他就“咔哒”按一下。一天下来,计数器上的总数是“总接客量”。但如果你是老板,你更想知道的是:“现在这一刻,一秒能进来几位客人?”这就是 QPS——Queries Per Second,每秒查询数。它不是一个累计数值,而是一个“流速”,就像自来水管里水的流速,你随时可以问:“现在每秒流过多少升水?”
在 AI 推理服务中,“客人”就是一个个推理请求(Query)。客户端把一张图片发过来,让模型判断“这是猫还是狗”,这就是一次查询。QPS 衡量的是:这一秒钟之内,系统成功处理了多少个这样的请求。注意关键词是“成功处理”——不是“接收了多少”,而是“完成了多少”。如果系统接收了 1000 个请求,但只成功返回了 800 个结果,那 QPS 只能算完成的那部分。
QPS 与响应延迟(Latency)是一对“欢喜冤家”。延迟是“每位客人从进门到坐下花了多久”,QPS 是“一秒钟能坐下几位客人”。餐厅里如果每桌客人要吃 2 小时(延迟高),那翻台率就低,一秒能接待的新客人就少。但如果你把上菜速度从 2 小时压到 30 分钟(降低延迟),同样数量的桌子就能接待更多客人,QPS 自然就上去了。
回到餐厅的比喻:你请了一个数据分析师,让他统计“10 分钟内进来了多少客人”,除以 600 秒,得到一个“平均每秒接客数”。这个数字很有用,但它会掩盖一个事实——晚上 7 点到 7 点 05 分可能挤进来 80 人,而 7 点 15 到 7 点 20 只有 10 人。平均 QPS 是 90/600=0.15 人/秒,但峰值时刻的瞬时 QPS 可能是平均的好几倍。所以,光看平均 QPS 远远不够,我们还需要一套更精细的“尺子”。
- 成功处理的请求总数指在统计窗口内,AI 服务真正完成并返回结果的请求数量。如果请求超时或报错,不算入分子。
- 统计时间窗(秒)计算 QPS 的时间范围。生产环境通常以 1 分钟或 10 秒为一个窗口,窗口太短会抖动明显,太长则会“抹平”尖峰。
- 整体比值的含义求出的 QPS 是该窗口内的“平均流速”。要捕捉瞬时高峰,需要缩小窗口或用下面要讲的峰值百分位数。
测量指标
继续经营你的餐厅。你决定在门口装一个智能摄像头,每秒记录一次“当前排队人数”。这个摄像头每秒产生一个数据点,积累起来就是一条随时间变化的曲线——这就是 QPS 时间序列。但面对成千上万个数据点,你如何快速判断餐厅经营得怎么样?你需要几个“浓缩指标”。
第一个是均值(Average)。把所有数据点加起来除以总数,得到平均 QPS。它告诉你系统“通常”处于什么水位。但均值有个大问题:它会被极端值“平均掉”。假设系统每秒稳定处理 100 个请求,偶尔有一秒处理了 1000 个(比如热点事件),均值会被拉高,让你误以为系统很空闲。反过来,若系统经常抖动到 0,均值也可能“看起来还行”。
第二个是峰值 QPS(Peak)。取所有数据点中的最大值。峰值决定了系统“最忙的那一刻”能不能扛住。如果峰值超过系统容量,就会产生超时和错误。就像餐厅的极限接待能力,不取决于平均客流,而取决于“最汹涌的那一波”能不能接住。
第三个是TP99(99th Percentile)。把所有 QPS 数据点从小到大排序,取第 99% 位置的那个值。它意味着“99% 的时间里,系统 QPS 都没超过这个值”。TP99 比峰值更稳健,因为它丢掉了最极端的 1% 的噪声数据。对应到延迟监控中还有个常用的 TP99(延迟的 99 分位),但这里我们关注的是 QPS 的 TP99。你可以把 TP99 理解为“去掉最疯狂的那 1% 时刻后,系统最忙的常态”。
用餐厅来理解:你的摄像头记录了 1000 秒的排队数据,按人数从少到多排好序。第 990 个位置对应的排队人数,就是“TP99 排队量”——它告诉你,在 99% 的时间里,队伍最长也就这么长。这对你决定“什么时候需要加开临时窗口”非常关键。同理,QPS 的 TP99 告诉你系统的“高水位常态”是多少,是容量规划的第一参考值。
无论用哪个指标,都必须关联成功率一起看。想象餐厅疯狂接客,但每道菜都做错了,客人纷纷退菜——这时候“每秒入座数”再高也是虚的。AI 服务也一样:如果 QPS 上去了但错误率飙升,说明系统正在“硬撑”,请求虽然收到了,但大量返回 5xx 错误。所以生产监控中,QPS 曲线要和成功率曲线放在同一张图里看。
- 采样排序假设系统每 10 秒采集一个 QPS 值,一共采集了 1000 个值。先把这 1000 个数从小到大排队。
- 确定百分位位置TP99 要找“99% 的数据都小于等于它”的那个位置。计算索引 index = 0.99 × 1000 = 990。
- 取出该位置的值排序后第 990 个值,就是 TP99。它比最大值小(因为丢了最后 1% 的极端值),但比均值大得多(因为它代表了高水位)。
影响因素
为什么有的 AI 服务一秒能处理 1000 个请求,有的只能处理 10 个?这背后有四个核心影响因素,如同餐厅的“硬件设施”和“运营流程”决定了你的接客上限。
第一是单请求延迟(Latency)。这是最根本的因素。如果一次模型推理平均耗时 100 毫秒,那么理论上单线程每秒最多处理 10 个请求(1000ms ÷ 100ms)。就像一位厨师做一道菜要 10 分钟,那他一个人一小时最多出 6 道菜。延迟越低,单个“服务员”能服务更多客人。推理的延迟主要来自模型计算量(FLOPs)、输入长度、模型结构(如 Transformer 的层数)等。
第二是批量大小(Batch Size)。现代 GPU 擅长“并行做事”。一次推理可以同时处理 8 张图片,成本远低于单独处理 8 次。这就是批处理(Batching)的威力。假设单次推理处理 1 张图需要 100ms,处理 8 张图需要 200ms,那 8 张图平均每张只花 25ms——吞吐量翻了 4 倍!这就像厨师一次炒一大锅菜,比一盘一盘炒快得多。
第三是显存带宽与算力上限。GPU 的计算能力(FLOPS)和显存带宽决定了“批量能开多大”。批量太大,显存装不下,或者计算单元已经饱和,再增大批量只会增加延迟而不再增加吞吐。这就像餐厅厨房面积有限,灶台就那么多,厨师再多也挤不进去。
第四是并发数(Concurrency)。服务能同时处理多少个请求?如果模型服务是单线程的,那一次只能处理一个请求;如果有多个 worker 进程或开启了多线程,就能同时处理多个。并发数越高,QPS 上限越高,但每个请求的延迟也可能变长(因为资源竞争)。
回到餐厅:你的“并发数”就像餐厅的包厢数——可以同时接待几桌客人;“批量大小”就像一个包厢能坐几个人;“单批时间”就是一桌客人从入座到离开的时长。QPS 就是“一小时内所有包厢累计接待的人数 ÷ 3600 秒”。要提高这个值,要么加包厢(提高并发)、要么每桌多坐几人(增大批量)、要么加速翻台(降低延迟)。理解了这四个因素,你就知道优化该往哪个方向使劲了。
- 并发数(Concurrency)可以同时处理请求的通道数。若服务开了 4 个 worker 进程,每个进程可同时跑 2 个推理任务,则总并发数为 8。
- 批量大小(Batch Size)每个推理任务中打包的请求数。GPU 一次前向传播处理的样本数。
- 单批推理延迟(Latency per Batch)处理完一整批请求所需的时间。注意批量增大时延迟会增长,但不是线性增长——8 张图的推理时间通常远小于 8 倍单张时间。
- 整体估算每秒能处理的总请求数 = 并发数 × 每批大小 ÷ 每批耗时。
瓶颈定位
餐厅经营惨淡,QPS 上不去,问题出在哪?是门口接待太慢?是后厨出菜太慢?还是服务员传菜太慢?你需要“全链路排查”。AI 推理服务也一样,一个请求从到达服务器到返回结果,要经过多个阶段。要定位 QPS 瓶颈,必须给每个阶段计时。
一条典型的推理请求链路包括五个环节:
1. 网络接收:请求从客户端到达服务器,经过负载均衡、网关(如 Nginx、Envoy)。
2. 预处理:CPU 上执行——解码 JSON、图像缩放、文本 Tokenization、归一化等。
3. 排队等待:请求在推理服务队列中等待 GPU 资源。
4. 模型推理:GPU 上的核心计算——Transformer 前向传播。
5. 后处理:CPU 上执行——softmax 求结果、拼装响应 JSON、返回客户端。
用“埋点计时”的方式,给每个环节打上时间戳,你就能看到时间花在哪了。这就像给餐厅的每个环节装上计时器:客人几点到门口、几点坐下、几点点上菜、几点吃上饭、几点离开。哪个环节耗时最长,哪个就是“瓶颈环节”。
定位瓶颈除了分段计时,还要看资源利用率。如果 GPU 利用率已经 99% 但 QPS 还是低,说明计算本身是瓶颈;如果 GPU 只有 30% 但 QPS 低,说明 CPU 预处理或数据传输(Host-to-Device 拷贝)在拖后腿。可以做一个实验:增大并发请求数,看 QPS 是跟着涨还是停滞——如果 QPS 涨到了一定程度就再也上不去,那个“天花板”就是瓶颈的位置。
餐厅的例子:你发现客人来了之后迟迟吃不上饭,于是让服务员记录每一桌“点完菜到上菜”的时间(相当于 T_infer 的逆过程——厨房出菜时间)和“坐下到点完菜”的时间(相当于 T_pre——接待效率)。结果发现,坐下后平均要等 20 分钟才能点菜,而出菜只要 5 分钟——瓶颈在服务员,不在厨师!同理,AI 服务的瓶颈可能根本不在 GPU 算力,而在 CPU 预处理环节。
- 网络时间(T_network)请求在网络上传输和网关转发的时间,通常几毫秒。如果这个值异常大,可能是网络带宽或网关配置的问题。
- 预处理时间(T_pre)CPU 花在数据转换上的时间。当输入图片很大或文本很长时,预处理可能成为瓶颈——CPU 忙不过来,GPU 却在“等米下锅”。
- 排队时间(T_queue)请求在队列里等待 GPU 的时间。这个值最能反映“系统是否过载”——如果它持续增长,说明请求进来的速度超过了处理速度。
- 模型推理时间(T_infer)GPU 上跑神经网络的时间。这是 AI 服务的“主业”,通常占总耗时的大头,但健康的系统中它应当占比 60%-80%。
- 后处理时间(T_post)把推理结果包装成响应的时间,通常很短。但若返回的 payload 很大(比如生成式 AI 输出长文本),也可能拖慢整体。
优化策略
找到了瓶颈,接下来就是对症下药。QPS 优化的策略可以归纳为三大类:让每次处理更高效、让资源更饱和、让没必要的计算消失。
策略一:动态批处理(Dynamic Batching)。这是提升 QPS 最有效的通用手段。核心思想是:把一小段时间内到达的请求攒起来,凑成一整批再送给 GPU 推理。就像餐厅把同一时间段入座的客人安排在几张桌上,厨师一次性炒几桌的菜。Triton Inference Server 和 vLLM 都内置了动态批处理功能。关键参数有 max_batch_size(最大批量)和 max_queue_delay(最大攒批等待时间)。攒批时间太长会增大延迟,太短则批量装不满——需要权衡。
策略二:模型加速。通过模型量化(Quantization)、结构剪枝(Pruning)、知识蒸馏(Distillation)等方式,让推理更快。量化把 FP16 的权重变成 INT8,计算量减半,显存占用减半,推理延迟显著降低。这就像厨师改用“预制菜”——提前做好的半成品,客人点菜后只需简单加热就能上桌,出菜速度大幅提升。
策略三:缓存复用(Caching)。如果大量请求是重复的(比如同一个热门问题),可以用缓存把结果存起来,后续相同请求直接命中缓存,不用再算。这就像餐厅的“招牌菜提前做好放在保温柜里”,客人一点就端出来。实际工程中可以用 Redis 或推理框架自带的 Prefix Caching(如 vLLM 的自动前缀缓存,对长对话非常有效)。
以下是量化对 QPS 影响的经验公式思路:
三种策略可以叠加使用,但要记住“木桶原理”——优化永远优先针对瓶颈环节。如果瓶颈在 CPU 预处理,你做再多的模型量化也无济于事,因为 GPU 早就空闲了。正确的做法是:先定位瓶颈,再选择对应的策略。这就像餐厅生意不好,你得先搞清楚是排队太长、上菜太慢还是菜品难吃,再决定是加椅子、换厨师还是换菜单。
- 量化前后的延迟对比先测出优化前单批延迟 L_before 和优化后延迟 L_after。量化模型的推理速度更快,因此 L_after 更小。
- 计算加速比加速比 = 优化前延迟 ÷ 优化后延迟。这个比值直接折算成 QPS 的理论提升倍数。
- 估算新 QPS假设系统资源不变,QPS 与单请求延迟成反比。延迟减半,QPS 理论上翻倍。
容量规划
餐厅开到第三年,你决定开分店。问题来了:新店的厨房要多大?几个厨师?几口灶?这就需要“容量规划”——根据预测的 QPS 需求,倒推出需要多少台服务器、多少张 GPU。
容量规划的关键步骤是压测(Load Testing)。在测试环境用工具(如 Locust、wrk、JMeter)向服务发起不同强度的请求,逐步加大压力,记录 QPS 和延迟的变化曲线。当你发现 QPS 不再增长,而是开始下降,同时延迟和错误率飙升——这个拐点就是系统的“极限容量”。就像测试一个厨师一秒最多能炒几道菜:让他不断加快节奏,直到他手忙脚乱出错的临界点。
压测后你会得到三个关键数据:单实例最大 QPS(QPS_max_per_instance)、目标 QPS 的 TP99 延迟、拐点对应的资源利用率。然后可以用简单的公式估算需要多少个实例:
规划完成后还需要配置梯度告警。别等到 QPS 超过极限才报警——那时候系统已经崩了。建议设置三个梯度阈值,就像水库的“汛限水位”:
- 黄线(60% 容量):预告警,提示流量正在上升,需要关注。
- 橙线(80% 容量):提示需要准备扩容或启用限流。
- 红线(100% 容量):立即自动扩容或触发降级保护。
餐厅的类比:你根据“周末晚上 7 点的预计客流”决定开几桌、雇几个服务员。如果预计客流是 200 人,而一张桌子一晚最多接待 20 人,你就需要 10 张桌子,再加 3 张备用桌(余量)。客流超过 8 成时你就该让服务员“加快翻台”(优化);超过 10 成时,你就得在门口挂“暂停接客”牌子(限流),否则整个餐厅都会乱套。
- 确定目标 QPS根据业务预测峰值流量。通常参考历史峰值的 1.5-2 倍,或结合业务活动日历预测。
- 获取单实例极限通过压测得到单个推理实例(一张 GPU)的最大稳定 QPS。这个值不是理论峰值,而是“延迟还在可接受范围内”的 QPS。
- 计算实例数并取整目标 QPS 除以单实例 QPS,向上取整。
- 加上余量系数乘 1.3(即多备 30% 的冗余),应对突发流量和单点故障。
AI 应用场景
场景一:大模型推理服务的容量预估
阶段:模型部署与上线规划
解决的问题:某公司准备将开源大语言模型(如 Llama-3-8B)部署为线上问答服务,CTO 需要知道:买 4 张 A100 够不够?传统做法是“拍脑袋”决定 GPU 数量,结果要么买多了浪费几十万成本,要么买少了上线第一天就被打爆。
具体案例:运维团队用 Locust 对部署好的模型服务进行持续压测,逐步将并发从 1 调到 64,记录每个并发下的 QPS 和 TP99 延迟。压测发现单张 A100 在 TP99 延迟 < 2 秒的约束下最大稳定 QPS 为 15。业务预测上线首月峰值 QPS 为 100,于是按公式计算:100 ÷ 15 × 1.3 ≈ 9 张 GPU。团队最终采购了 10 张 A100(8 张 + 2 张冗余),上线后实际峰值 QPS 达到 95,系统平稳运行。
场景二:交易风控系统的实时告警
阶段:在线监控与运维
解决的问题:某支付公司的风控模型每秒要处理数千笔交易。如果 QPS 突然暴跌,说明模型服务可能挂掉了;如果 QPS 正常但延迟飙升,说明即将过载。传统监控只看 CPU 和内存,无法直接感知“业务吞吐健康度”。
具体案例:监控平台接入 Prometheus + Grafana,每 5 秒采集一次风控模型的 QPS 和 TP99 延迟数据。设置告警规则:QPS 低于基线 50% 持续 1 分钟触发 P0 告警,TP99 延迟超过 800ms 触发 P1 告警。一次真实故障中,某模型因上游特征服务超时导致 QPS 从 3000 跌到 800,系统在 1 分钟内发出告警,值班工程师及时发现并降级了模型,避免了支付链路阻塞。
Python 演示
"""QPS 实时监控与容量规划计算器模拟 AI 推理服务的请求处理,计算实时 QPS、TP99,并根据压测结果估算所需实例数。"""import timeimport randomfrom collections import deque class QPSMonitor: def __init__(self, window_size=10): self.window = deque(maxlen=window_size) self.samples = [] # 存放每个时间窗口的 QPS 记录 self.request_count = 0 self.window_start = time.time() def record_request(self): self.request_count += 1 def update(self): now = time.time() elapsed = now - self.window_start if elapsed >= 1.0: qps = self.request_count / elapsed self.window.append(qps) self.samples.append(qps) self.request_count = 0 self.window_start = now return qps return None def avg_qps(self): if not self.window: return 0.0 return sum(self.window) / len(self.window) def peak_qps(self): if not self.window: return 0.0 return max(self.window) def tp99(self): if len(self.samples) < 10: return 0.0 sorted_samples = sorted(self.samples) idx = int(0.99 * len(sorted_samples)) - 1 return sorted_samples[max(idx, 0)] def simulate_traffic(monitor, duration=30): """模拟 30 秒的推理请求流量""" end_time = time.time() + duration while time.time() < end_time: # 模拟请求到达:平稳期每秒约50个,突发期翻倍 if int(time.time()) % 10 >= 8: rate = 120 else: rate = 50 for _ in range(rate): monitor.record_request() time.sleep(0.02) monitor.update() def plan_capacity(target_qps, single_instance_qps, margin=1.3): import math return math.ceil(target_qps / single_instance_qps * margin) def main(): monitor = QPSMonitor(window_size=10) print("开始模拟推理流量...") simulate_traffic(monitor, duration=30) print("\n==== QPS 监控统计 ====") print(f"平均 QPS: {monitor.avg_qps():.1f}") print(f"峰值 QPS: {monitor.peak_qps():.1f}") print(f"TP99 QPS: {monitor.tp99():.1f}") target = 200 capacity = 80 instances = plan_capacity(target, capacity) print(f"\n==== 容量规划 ====") print(f"目标 QPS: {target}, 单实例极限 QPS: {capacity}") print(f"建议实例数: {instances}(含30%余量)") if __name__ == "__main__": main()
self.window = deque(maxlen=window_size)用固定长度的双端队列保存最近的 QPS 采样值,滚动统计时自动丢弃旧数据。self.request_count += 1每次收到请求就累加计数器,这是计算 QPS 的原始数据来源。elapsed = now - self.window_start计算距离上次刷新的时间差,当超过 1 秒时计算一次 QPS。qps = self.request_count / elapsed用窗口内的请求数除以秒数,得到这一秒的平均速率,即 QPS。self.window.append(qps)把新算出的 QPS 值加入历史窗口,保留最近 10 秒的数据用于统计。return sum(self.window) / len(self.window)对窗口内所有 QPS 取平均,得到“平均 QPS”水位。return max(self.window)取窗口内的最大值,得到“峰值 QPS”——容量规划的关键参考。sorted_samples = sorted(self.samples)把所有历史 QPS 采样值排序,为计算 TP99 做准备。idx = int(0.99 * len(sorted_samples)) - 1计算百分位位置,取第 99% 分位的值作为 TP99 的估算。for _ in range(rate)模拟请求到达:循环生成一批请求并记录,休息 0.02 秒后继续。math.ceil(target_qps / single_instance_qps * margin)用目标 QPS 除以单实例容量乘以 1.3 余量,向上取整得到实例数。
常见误区
误区“QPS 这个数字越大,说明我的 AI 服务越强,性能越好。我要不惜一切代价把 QPS 刷上去!”
正解QPS 只有在“保证延迟和成功率合格”的前提下才有意义。如果为了提升 QPS 而把批量开得巨大,每个请求的延迟从 100ms 涨到 3 秒,用户体验急剧恶化——这就像餐厅为了多接客,让所有客人拼桌挤在一起,结果每桌客人都吃得很难受,下次再也不来了。正确做法是设定延迟 SLA(如 P99 < 500ms),在其约束下最大化 QPS。
为何常见:很多人看到 QPS 指标就以为是“跑分”游戏,忽略了它背后是延迟、成功率、资源成本的多目标平衡。业务方的“快”是体验指标,而 QPS 只是系统指标。
误区“我看了监控面板,平均 QPS 才 50,系统很空闲啊,不用扩容。”
正解平均 QPS 会严重掩盖峰值风险。假设流量模式是 1 秒来 200 个请求,接下来 9 秒完全空闲,平均 QPS 只有 20,但系统在那一秒已经过载崩溃。正确做法是同时关注峰值 QPS 和 TP99,用峰值(而不是均值)来做容量规划。这就像水库蓄水,你要看的是汛期最高水位,而不是全年的平均水位。
为何常见:人类直觉上习惯用“平均”来总结数据,但在流量具有显著突发性时,均值失真严重。
误区“AI 推理就是 GPU 算的,QPS 上不去肯定是 GPU 不够,加卡就行了!”
正解很多实际案例中,瓶颈在 CPU 预处理、数据传输或网络 IO。比如输入图片需要大量解码和缩放操作,CPU 忙不过来,GPU 闲置率高达 60%。加再多 GPU 也无济于事。通过全链路分段计时(如上文 T_pre / T_infer 分别埋点),先确认瓶颈环节再投入资源,才是正确姿势。
为何常见:AI 服务给人的第一印象就是“GPU 在干活”,容易忽略同样耗时的数据准备环节。这就像人们催“厨师太慢”时,其实可能是传菜员在偷懒。
误区“压测显示单机能扛 200 QPS,那我上 5 台就能扛 1000 QPS 了,就这么定了!”
正解压测环境通常比生产环境“干净”:没有真实流量的波动、没有其他服务的资源争抢、没有网络的随机抖动。生产环境的 QPS 通常只有压测结果的 60%-70%。这也是前面公式里要乘 1.3 余量的原因。同时,生产环境的模型输入长度、并发模型可能和压测差异巨大——压测必须和真实业务形态对齐。
为何常见:工程师容易把实验室数据当成生产承诺,忽略了真实环境的复杂性和不确定性。
面试题
Q1. 以下对 QPS 的描述,最准确的是哪一项?
- A.QPS 是系统接收到的请求总数量
- B.QPS 是每秒成功处理的请求数,反映瞬时吞吐能力← 正确答案
- C.QPS 与延迟完全无关,只与硬件有关
- D.QPS 应该越高越好,不需要考虑延迟约束
答案:B。QPS 是 Queries Per Second,指的是每秒成功处理的请求数,重在“成功”和“每秒”两个限定词。选项 A 错在把速率当成总量;C 错在 QPS 与延迟强相关;D 错在必须在延迟 SLA 约束下追求 QPS,不能盲目求高。
Q2. 关于 TP99 指标,以下说法正确的有哪些?
- A.TP99 是对所有 QPS 采样数据排序后的第 99 百分位值← 正确答案
- B.TP99 比最大值更能代表系统的常态高水位← 正确答案
- C.TP99 一定大于等于平均值← 正确答案
- D.TP99 一定小于等于中位数
答案:ABC。TP99 是排序后取 99% 位置的值,它丢了最极端的 1% 噪声数据,所以比最大值更稳健,且通常明显大于均值,故 A、B、C 正确。对于右偏分布,TP99 必然大于中位数,D 错误。
Q3. 一个 GPU 推理单机压测显示最大 QPS 为 50,目标是支撑 300 QPS 的业务峰值,考虑 30% 余量,至少需要几台实例?
- A.6 台
- B.7 台
- C.8 台← 正确答案
- D.10 台
答案:C。计算公式为 N = ⌈300 ÷ 50 × 1.3⌉ = ⌈7.8⌉ = 8 台。6 台没有考虑任何余量,7 台的理论总容量 350 但乘余量系数后不足 300×1.3=390,只有 8 台才能满足 30% 余量的要求。
Q4. 在推理链路中,哪个信号最能说明 GPU 已经过载、请求在排队等待?
- A.预处理时间突然变短
- B.排队等待时间(T_queue)持续增长← 正确答案
- C.后处理时间显著下降
- D.网络传输时间归零
答案:B。当请求到达速度超过 GPU 处理速度时,请求就会在队列中堆积,表现为 T_queue 持续增大。这就像一个堵车的收费站,排队队伍越来越长。其他选项都是“变快/变短”,与过载现象矛盾。
Q5. 以下哪些措施可以直接提升 AI 推理服务的 QPS?
- A.启用动态批处理聚合多个请求← 正确答案
- B.对模型进行 INT8 量化降低单请求延迟← 正确答案
- C.增加请求的输入文本长度
- D.对热门请求结果做缓存复用← 正确答案
答案:ABD。动态批处理让 GPU 一次处理更多请求,量化降低延迟从而提升单通道吞吐,缓存直接跳过了计算——三者都能提升 QPS。增加输入长度反而会增大计算量和延迟,降低 QPS,所以 C 错误。
Q6. QPS 监控中,为什么要把“成功率”和 QPS 放在一起看?
- A.因为成功率影响报表美观
- B.因为 QPS 高但错误率高说明系统在硬撑,吞吐可能是虚的← 正确答案
- C.因为成功率是 KPI,QPS 不是
- D.因为两者没有关系
答案:B。QPS 只统计“成功处理”的请求,但如果系统过载时大量请求报 5xx 错误,QPS 可能表面正常甚至偏高,实际服务质量已经崩溃。因此必须结合成功率判断“有效 QPS”。这就像餐厅说“每秒接待了 10 桌”,但如果 8 桌都在投诉菜品,这数字没意义。
Q7. 均值 QPS 为 100,峰值 QPS 为 500,这最可能说明什么?
- A.系统非常稳定,不需要关注
- B.流量分布极度不均,存在明显突发,容量规划应以峰值为参考← 正确答案
- C.均值计算错误,应该改成中位数
- D.峰值数据是噪声,可以忽略
答案:B。均值与峰值之间 5 倍的差距说明流量具有强突发性。如果只按均值 100 规划容量,突发时刻到 500 时系统必然过载。正确做法是参考峰值和 TP99 做容量规划,并配置提前告警。这种“平均很空闲、峰值很凶猛”的模式在秒杀、热点事件中很常见。
Q8. 关于推理服务的容量规划,以下说法正确的有哪些?
- A.压测得到单实例最大 QPS 后,直接用它作为生产容量标准
- B.容量规划应预留一定余量以应对流量波动和单点故障← 正确答案
- C.压测必须模拟真实的输入规模和并发模型← 正确答案
- D.告警阈值应该设置到 100% 容量时再触发,避免误报
答案:BC。生产环境比压测环境复杂,通常要预留 30% 余量,所以 A 错误、B 正确。压测若和真实流量形态偏差大,结果就不可信,C 正确。告警应分梯度提前到 60%/80% 触发,D 认为等到 100% 才告警会错过最佳处理时机。
Q9. 其他条件不变,将单请求延迟从 200ms 优化到 80ms,理论上 QPS 提升多少倍?
- A.1.5 倍
- B.2.0 倍
- C.2.5 倍← 正确答案
- D.3.0 倍
答案:C。QPS 与单请求延迟成反比(QPS ≈ 1/延迟 × 并发×批量)。200ms 到 80ms,延迟变为原来的 0.4 倍,QPS 提升 200÷80=2.5 倍。注意这是单通道的理论估算,实际受批处理拼接效率、资源竞争等影响会略低。
Q10. 在 GPU 利用率只有 20% 但 QPS 很低的情况下,最可能的原因是什么?
- A.GPU 算力不足,需要换更贵的卡
- B.CPU 预处理或数据加载环节存在瓶颈,GPU 在等待数据← 正确答案
- C.QPS 监控面板坏了
- D.模型太大,显存放不下
答案:B。GPU 利用率低但吞吐上不去,典型的“供血不足”——数据来不及喂给 GPU。CPU 上做图像解码、文本 tokenize 太慢,或 Host-to-Device 拷贝耗时过长,GPU 只能空转。这就是“厨房里厨师闲坐着,但传菜员没把食材送来”。应该优化预处理管线或增加 CPU 资源,而不是换 GPU。