FDE Times 数据在招 FDE 职位 838▼55 近 7 天在招职位数的变化(同口径比较):不计入本周新开始追踪的公司的职位近 7 天新增 66在招公司 169支持远程 24%美国薪资中位数 $200k招聘最多 Palantir 95
ENVI

前线部署工程师(FDE)的专业媒体

技能指南 · 指南

客户架构师说系统会崩?那就一起压测

开跑之前先商定通过标准、环境和场景,质疑者就成了测试结果的共同作者。

分享微博

要点速览

  • 不要争论系统会不会崩,而是和客户一起写清楚怎么测出它在哪里崩。
  • 先商定阈值,使用数据量充足、接近生产环境的环境,先测单个组件,再测整个系统。
  • 把负载推到超出预期的水平,同时测量恢复情况,最后用 ADR 记录决策。
折线图展示 k6 三阶段场景中并发用户数随时间的变化:基线阶段 50 个用户持续 15 分钟,p95 阈值低于 800 毫秒;压力阶段从第 15 分钟到第 30 分钟逐步增加到 200 个用户,用于寻找崩溃点;恢复阶段从第 30 分钟到第 40 分钟保持 25 个用户。图中在约 140 个用户处标出崩溃点,此时 p95 急剧上升。
只有基线阶段和恢复阶段设有通过/失败阈值,压力阶段的作用是找出设计的上限。来源:文中的 k6 脚本和假设结果。

架构评审已经进行了 40 分钟。你刚介绍完一个要部署在客户侧的文档搜索服务的设计,对方的首席架构师双臂交叉:“每个请求都同步经过同一个数据库,到了高峰期肯定会崩。”

你认为设计没有问题,他认为一定会崩。你们争论的是一件还没发生的事,谁也没法靠嘴赢,而多吵一分钟,客户对你的信任就少一分。

吵得更好也没用。更好的做法是,邀请他一起设计那个可能证明他是对的测试。优秀的前线部署工程师(FDE)和只会写代码的人,差别就在这项技能:把分歧变成一场实验,而评判标准由双方事先商定。

为什么测试能让争论降温?

因为它改变了问题本身。“会不会崩?”是信念之争;“在多大负载下崩、哪个组件先出问题?”是工程问题,而每个工程师都想知道答案。

在 Google,要安全地运行一个系统,必须先了解它的极限。Google 的 SRE 书中明确写道,工程师用压力测试找出 Web 服务的极限,负载测试能揭示崩溃点,这是容量规划的基础知识。

这样看,架构师的警告并不是麻烦,而是一条还没人写下来的测试需求。

当你说“您说得对,我们确实不知道崩溃点在哪里,一起把它找出来吧”,他就从批评者变成了共同作者。无论结果如何,测试方法从一开始就得到了他的认可。

阈值必须在开跑之前签字确认

危害最大的错误,是先跑测试,再讨论结果意味着什么。到那时,双方都会按对自己有利的方式解读图表。AWS Well-Architected 正是把这一点列为反模式:没有定义清晰、可度量的性能要求,例如响应时间、吞吐量和可扩展性目标。

Grafana k6 为此内置了一套机制:thresholds,即为每个指标声明的通过/失败标准。阈值就写在测试文件里,双方商定的内容因此保存在版本控制中,而不只是会议纪要里的一行字。

第二件要商定的事是在哪里跑。AWS 提醒,缩小规模的测试环境可能误判系统在生产环境中的表现。如果你在一台很小的预发布机器上跑,系统扛住了,架构师完全有理由不认这个结果。所以,让他来选环境。

一个完整的示例

沿用上面的场景,并假设一些数字。经过 20 分钟的讨论,双方商定:正常负载是 50 个并发用户,架构师担心的峰值是它的四倍。正常负载下的通过阈值是 p95 低于 800 ms、错误率低于 1%。

架构师又补充了一个你没想到的问题:如果系统在高峰期崩溃,负载要降到多少它才能自行恢复?Google 的 SRE 书也提出过同样的问题:当部分服务器在高负载下崩溃时,负载要降到多低,系统才能重新稳定?于是,场景分为三个阶段。

import http from 'k6/http';
import { check } from 'k6';
import { SharedArray } from 'k6/data';

// 客户提供的真实(已脱敏)查询,不是编造的
const queries = new SharedArray('queries', () => JSON.parse(open('./queries.json')));

export const options = {
  scenarios: {
    baseline: { executor: 'constant-vus', vus: 50, duration: '15m' },
    stress: {
      executor: 'ramping-vus', startTime: '15m', startVUs: 50,
      stages: [{ duration: '10m', target: 200 }, { duration: '5m', target: 200 }],
    },
    recovery: { executor: 'constant-vus', startTime: '30m', vus: 25, duration: '10m' },
  },
  thresholds: {
    // 双方签字认可的阈值:只适用于正常负载和恢复阶段
    'http_req_duration{scenario:baseline}': ['p(95)<800'],
    'http_req_failed{scenario:baseline}': ['rate<0.01'],
    'http_req_duration{scenario:recovery}': ['p(95)<800'],
  },
};

export default function () {
  const q = queries[Math.floor(Math.random() * queries.length)];
  const res = http.post(`${__ENV.BASE_URL}/search`, JSON.stringify({ q }),
    { headers: { 'Content-Type': 'application/json' } });
  check(res, { '状态码 200': (r) => r.status === 200 });
}

注意,stress 阶段没有设阈值。它不是用来通过的,而是用来找崩溃点的。k6 按目的给测试分类,压力测试用来观察系统在极限状态下的表现,即负载超出预期平均水平时会怎样。

AWS 同样把“没有把负载推到预期上限之外”列为反模式。

假设结果如下:基线阶段通过;压力阶段用户数超过约 140 后,p95 急剧上升;恢复阶段通过。你们俩都说对了一部分。这个设计能扛住当前负载,但存在上限,而现在双方都看得到上限在哪里。

这里的恢复阶段只测了一个水平,即 25 个用户,所以只能说明系统在这个水平下能否恢复。要完整回答架构师的问题,就把它换成一个分多级降低负载的 ramping-vus,比如 150、100、50,最后 25,并记录 p95 首次回到 800 ms 以下的那一级。

在客户现场自己动手的步骤

尽早开始。Ed Glas 在 Microsoft 博客的一篇文章中指出,许多性能问题出在架构层面,不是上线前临时就能修好的。如果架构师有顾虑,就在这周测,而不是等到上线那周。

测量之前先灌入足够的数据。正如 Ed Glas 所说,许多性能问题只有在数据量很大时才会出现。一个只有 10,000 条记录的数据库,没法检验“这个数据库将来要存几千万条记录”的担忧。

先测单个组件,再测整个系统。Google SRE 指出,每个组件都有自己的崩溃点,都需要单独做负载测试;Ed Glas 则建议从单一事务开始,再到混合事务,最后才是整个系统。

在上面的示例中,场景保持不变,只把 BASE_URL 指向一个只执行数据库查询的端点。如果它比整个系统更早崩溃,你就找到了罪魁祸首。

最后,把结果写下来。架构决策记录(ADR)记录一项架构决策,以及背后的理由、权衡和后果。一份类似“保留同步设计,实测上限约 140 个用户,实际负载达到 100 时引入队列”的 ADR,能把测试结果变成一项有条件的承诺,三个月后谁也不用从头再吵一遍。

让联合测试适得其反的错误

最常见的错误是自己写好场景,再请客户来看结果。没有参与设计测试的客户,不会信任测试结果。让架构师来选峰值负载和测试环境,即使你觉得他的数字有点悲观。

第二个错误是使用编造的查询。一份只有五条查询、反复循环的列表会全部命中缓存,p95 会好得可疑。向客户要一份真实的、已脱敏的查询样本。

第三个错误是把压力阶段当成必须通过的考试。如果你回避把系统推到崩溃点,架构师会认为你害怕答案。找到崩溃点是双方共同的收获,而不是你的失败。

最后一个错误是忘了恢复阶段。高峰期变慢、之后自行恢复的系统,和一崩就起不来的系统截然不同。直接问架构师更担心哪种情况,由他的回答决定恢复阶段要测得多细。

把它写进简历

简历上不要只写“进行了负载测试”,可以这样写:与客户架构团队共同设计联合负载测试,在运行前商定 p95 阈值,定位数据库崩溃点,并用 ADR 记录决策。

面试 FDE 岗位时,准备好讲一段这样的经历,因为它说明你能用数字而不是嗓门来化解与客户的技术分歧。

本周练习:回想上一次你和别人在性能问题上意见不合的情形。写下双方本该事先商定的三个数字,再写一个用来检验它们的三阶段场景。下次再有人双臂交叉说“它会崩”,你就有现成的回答:“好,我们一起看看它在哪里崩。”

这篇文章对你有帮助吗?

7 个信源
路线图上的下一篇 · 阶段 4: 客户工作FDE面试讲坏消息,关键在你事后做了什么故事要控制在90秒内,因为行为题几乎出现在每一轮,甚至会插在技术面中途。