性能测试:生产系统压测的风险与控制策略

生产压测一直是性能测试里最敏感、也最容易引发争议的话题之一。

支持生产压测的判断通常是:

  • 只有生产环境最真实
  • 不在生产压,很多风险根本看不到

反对它的人也有很强的理由:

  • 一旦失控,代价太大
  • 用户、数据、第三方依赖都可能被误伤

这两边都没有完全错。
生产压测真正难的,不在“要不要做”这么简单,而在:

如果真要做,怎样把风险降到一个可控、可接受、可快速止损的范围内。

所以更愿意把生产压测理解成一场受严格约束的风险实验,而不是一次“更接近生产流量的普通压测”。

一、生产压测真正的风险,不只是“把系统压挂”

一提生产压测,脑子里只有一种风险:

  • 系统会不会被打挂

但从真实项目经验看,更常见、也更隐蔽的风险其实包括:

  • 误伤真实用户流量
  • 写入真实脏数据
  • 触发真实风控、告警、补偿、发券、发消息链路
  • 放大第三方调用成本
  • 把缓存、消息、数据库状态污染到生产

也就是说,生产压测的风险不只是“慢”和“挂”,更可怕的是“业务污染”和“外部副作用”。

如果这一层不先想清楚,生产压测很容易变成一次代价昂贵的误操作。

二、生产压测首先要解决的,不是施压方式,而是隔离方式

如果要只保留一个原则,那就是:

生产压测更稳的顺序是先解决隔离,再考虑加压。

常见的隔离思路包括:

  • 压测流量标识
  • 压测账号池
  • 压测数据空间
  • 压测白名单
  • 压测消息主题或影子队列
  • 影子表、影子库、影子索引

重点不在于形式多高级,而在于是否能回答这几个问题:

  • 压测流量能不能和真实用户请求区分开
  • 压测写入的数据能不能回收
  • 压测触发的副作用能不能被限制在可控范围

如果这三件事做不到,生产压测基本就不该开始。

三、生产压测最容易出事故的地方,是副作用链路没有提前盘清楚

很多系统不是一个请求结束就完了。
一次生产请求背后可能会连带触发:

  • 短信
  • 邮件
  • 推送
  • 工单
  • 积分
  • 优惠券
  • 风控
  • 异步补偿
  • 第三方支付或回调

如果这些副作用链路没有在压测前逐个确认清楚,生产压测最容易发生的事情不是“性能问题”,而是“业务事故”。

所以通常会要求在压测前列一张非常明确的副作用清单:

  • 哪些链路会被真实触发
  • 哪些要屏蔽
  • 哪些要走影子通道
  • 哪些可以保留但必须限量

这一步通常比写脚本更重要。

四、更推荐的生产压测推进顺序:先探测,再扩面,再升压

生产压测最忌讳的方式,就是:

  • 方案没收紧
  • 隔离没验证
  • 监控还没盯稳
  • 一上来就打峰值

这类操作一旦出事,通常连回头空间都很小。

更倾向的顺序通常是:

1. 低流量探测

目的:

  • 验证压测流量有没有被正确识别
  • 验证压测标识、影子数据、隔离策略有没有生效
  • 验证告警、监控和止损链路是否可用

2. 小范围放量

目的:

  • 观察系统和依赖是否出现意外副作用
  • 确认真实生产流量和压测流量是否发生冲突

3. 分段升压

目的:

  • 在可观测前提下逐步逼近目标负载
  • 识别退化拐点
  • 保留及时止损空间

生产压测不是越快越好,而是越可控越好。

五、生产压测必须提前定义“谁有权停止、什么情况下停止”

这是生产压测里最容易被忽略、但极其重要的一点。

会认真准备脚本和方案,却没有认真准备“怎么停”。

通常要求在执行前就明确:

1. 停机线

例如:

  • 错误率超过某阈值
  • 关键依赖资源超阈
  • 用户投诉开始出现
  • 第三方服务异常

2. 决策人

也就是谁能明确拍板:

  • 暂停
  • 继续
  • 终止

如果这件事不提前约定,现场一旦出异常,最常见的情况就是:

  • 每个人都看到了风险
  • 但没人敢先喊停

这时候风险往往会比系统本身的问题扩散得更快。

六、在项目里最看重的几类生产压测控制策略

1. 压测流量标识需要贯穿链路

不能只在入口层加个 header 就算完。
更理想的方式是让它在日志、监控、调用链、下游服务里都可识别。

否则一旦出问题,你甚至分不清:

  • 当前看到的异常到底是生产真实流量,还是压测流量带来的

2. 数据需要可回收

如果压测会写生产数据,那你至少要回答:

  • 这些数据如何标记
  • 这些数据如何清理
  • 清理失败怎么办

否则压测结束以后,脏数据会持续污染业务分析和后续流程。

3. 第三方调用需要提前设边界

很多系统最容易出问题的,不是自己扛不住,而是把第三方打穿、打超费、打进风控。
生产压测前,这一层必须单独确认。

4. 监控要提前进入“压测视角”

不能压测开始了才临时找图。
更好的方式是提前明确:

  • 入口流量图
  • 业务成功率
  • 核心依赖资源
  • 压测流量识别维度

七、在项目里踩过的几个典型坑

坑 1:只隔离了入口,没有隔离下游副作用

表面上看请求是压测流量,实际上消息、通知、补偿还是走了真实链路。
这种问题非常危险,因为现场一开始可能根本看不出来。

坑 2:压测账号是独立的,但写数据还是进了真实业务域

用了压测账号并不代表就万事大吉,如果订单、工单、消息、日志等仍然写在真实域里,污染照样会发生。

坑 3:监控没做压测流量切分,结果现场只看到“全局异常”

这类情况一出现,现场会非常混乱,因为没人能快速判断:

  • 是压测在伤系统
  • 还是本来就有线上波动

坑 4:没有明确停机线,现场靠感觉判断

这是我最不推荐的做法。
生产压测最怕“再观察一下”,因为很多风险扩散并不会给你太多缓冲时间。

八、排查生产压测方案是否靠谱时,通常先看什么

1. 先看隔离设计

确认:

  • 压测流量是否可识别
  • 压测数据是否可回收
  • 副作用链路是否已处理

九、生产压测前会直接拉一张执行清单

生产压测不能只靠口头确认。
如果真要做,通常会拉一张显式清单,执行前逐项勾掉。

例如:

检查项 是否完成 备注
压测流量 header 已贯穿入口和下游 是/否 包括日志和调用链
压测账号池已准备 是/否 可区分真实用户
写入数据可标记、可回收 是/否 已验证清理脚本
短信、邮件、推送已屏蔽或走影子通道 是/否 防止副作用扩散
第三方接口限流边界已确认 是/否 避免外部成本和风控
监控面板已切好压测视角 是/否 可区分压测流量
停机线和决策人已确认 是/否 现场可立即止损

这张表没有技术门槛,但极其有用。
因为生产压测很多事故,本质上都是“以为确认了,其实没人真确认”。

十、更常用的一套生产压测推进节奏

如果隔离设计已经准备好,通常也不会一上来就放大流量。
更常见的节奏是:

  1. 先打极小流量,验证流量标识和副作用隔离
  2. 再做 5 到 10 分钟小范围放量
  3. 观察用户指标、业务指标和依赖指标都稳定后,再进入正式升压
  4. 每次升压前都做一次“是否继续”确认

现场通常会把继续条件写得非常具体:

  • 当前错误率仍低于阈值
  • 没有真实用户投诉
  • 第三方调用没有异常放大
  • 压测流量与真实流量仍可清晰区分

如果这些条件里有一条解释不清,就不继续加压。

十一、真出问题时怎么止损

生产压测不是不能出问题,而是必须准备好问题一出现就能收住。

通常会预设下面几个动作:

  1. 立即停止入口压测流量
  2. 冻结当前阶段参数和监控截图
  3. 确认异常是否仍在持续
  4. 如果异常仍在,回看是否有副作用链路未被切断
  5. 先恢复业务,再讨论根因

这里有个很现实的原则:

生产压测现场,止损优先级永远高于根因分析。

根因可以会后慢慢看,但真实业务和真实用户不能拿来等分析结论。

2. 再看监控和止损机制

确认:

  • 关键指标是否能实时观测
  • 谁来拍板停止是否明确

3. 再看施压策略

确认:

  • 是不是分阶段推进
  • 有没有低流量探测环节

4. 最后才看脚本与工具

因为生产压测最大的风险很多并不是来自脚本本身,而是来自边界没控住。

结语

生产压测的核心从来不是“敢不敢压”,而是能不能在真实用户、真实数据、真实依赖都在线的情况下,把这场实验设计得足够可控。

更准确地说,生产压测最少要做到:

  • 流量可识别
  • 数据可回收
  • 副作用可隔离
  • 风险可观测
  • 现场可止损

如果这些基础都没补齐,生产压测很容易变成一次高风险冒险;
只有把隔离、监控、回退和停机线都设计好,它才有资格成为一场可控验证。