S30

性能分析方法

点击正文段落选定收藏或划线位置;未选定时使用屏幕内第一段。

课内目录

1 性能分析要回答的问题

“机器变慢了”还不是可以验证的性能问题。它可能指 shell 登录后迟迟没有提示符,也可能指目录列表很快、读取文件却很慢,或者某个网络服务大部分请求正常、少量请求等待数秒。分析的起点是把感受改写成有对象、有时间范围、有负载条件的陈述:某主机上的文件查询服务,在并发数为 32 时,最近 10 分钟请求延迟的 p99 从 180 ms 升到 900 ms,而完成速率没有增加。这样的陈述才允许别人复现,也允许我们判断修改是否有效。

性能分析通常要回答 4 个问题:用户等待在哪里发生,什么资源或依赖限制了进展,什么变化触发了退化,以及改动后是否真的改善。它们不能由某张仪表盘自动回答。CPU 使用率是主机忙碌程度的线索,用户延迟是请求完成时间的描述,两者观察的对象不同。低 CPU 可以伴随长时间磁盘等待,高 CPU 也可能只是程序正在有效完成大量任务。先定义“好”的含义,才能判断某个数字是在解释问题,还是只与问题同时出现。

平均值适合描述总体趋势,却容易遮住少量长等待。把请求耗时从小到大排列,p95 表示约 95% 的请求不超过这个位置对应的耗时,p99 同理。它们不是“最慢请求的平均值”。当样本只有 20 个时,p99 几乎贴着最大值,波动会很大;当统计只包含成功请求时,大量超时可能反而让成功请求的分位数看起来更好。因此延迟必须和请求数量、错误、超时、统计窗口放在一起读。

可以先画出实际路径:客户端发送请求,服务进程接收任务,查找文件,读取内容,再返回响应。路径中的每段都可能运行、排队或等待。总体耗时包含这些时间,但不能直接把各段的 p99 相加当成总体 p99,因为各段最慢的请求未必相同。入门阶段先学会沿同个请求找边界:请求何时到达,何时开始处理,何时发起文件读取,何时完成。记录相同的请求标识和明确的计时口径,比同时打开更多工具更有价值。

性能问题从用户目标沿请求路径映射到资源
性能问题从用户目标沿请求路径映射到资源

本课采用 Linux 主机上的进程、文件与网络服务作为练习背景。命令输出会随系统版本变化,应先确认目标进程、执行权限和统计单位。每次调查都留下简短记录:症状、发生时间、负载、最近变更、当前假设与反证。比如“读文件慢”与“打开文件慢”需要不同证据;文件不存在导致的重试,也不等于磁盘吞吐不足。性能分析的产物应是可检查的解释,而不只是“重启之后好了”。

2 USE / RED 等方法论

USE 从资源出发,分别观察利用率、饱和度和错误。利用率回答资源在观察窗口内有多忙,饱和度回答是否已经有工作排队或无法立即得到服务,错误回答是否存在失败、丢弃或异常。对 CPU,可以观察各核心忙碌情况、可运行任务的排队线索以及进程异常退出;对存储,可以观察设备忙碌时间、等待和队列、读写错误。不同资源的指标定义不同,不能把所有百分比都理解成“还剩多少容量”。

尤其要区分利用率和饱和度。某进程只有 1 个忙碌线程,在 16 个逻辑 CPU 的机器上可能接近占满 1 个核心,但主机平均 CPU 看起来仍低。反过来,存储设备的忙碌百分比接近 100%,也不能单凭这个值判断已经到达最大吞吐;设备可能同时处理多个请求。USE 的作用是提醒我们补齐观察维度,再结合队列、完成速率和延迟解释,而不是提供“超过 80% 就扩容”的通用公式。

RED 从服务请求出发,观察速率、错误和耗时。速率应说明是到达速率还是完成速率,错误应说明包含哪些退出状态、响应码和超时,耗时应说明从哪里开始计时。服务每秒完成 200 个请求,不代表每秒只收到 200 个请求;如果每秒到达 240 个,积压仍在增长。客户端已超时而服务端仍继续工作时,服务端“成功完成”的数字也可能与用户体验脱节。定义边界是使用方法论的前提。

在主机侧,可以用 uptime 获取负载线索,用 vmstat 1 10 连续观察进程、内存和 CPU 的变化,用 pidstat -u -d -p 1234 1 10 看指定进程的 CPU 与 I/O 活动,用 iostat -xz 1 10 看设备统计。这些工具中有的来自额外软件包;首份报告也可能是自开机以来的累计平均值,应阅读本机帮助并区分后续区间。Linux 的负载平均值还包括某些等待状态的任务,不能把它直接当成 CPU 使用率。

在服务侧,至少同步记录请求数、失败数、超时数和延迟分布。先用 RED 确认用户影响,再用 USE 缩小资源范围,通常比从所有主机指标里寻找异常更省力。例如完成速率持平、p99 上升、设备队列增长,可以形成“文件读取排队”的假设;如果只有错误率上升且日志显示权限拒绝,就应该优先检查路径和权限。方法论帮助组织问题,但不会代替证据。

RED 定位影响,USE 检查资源,再回到假设验证
RED 定位影响,USE 检查资源,再回到假设验证

练习时可以把调查限定为 1 个窗口:先记下 60 秒的用户指标,再选择相关资源采样相同的时间段。时间对齐非常关键。若服务延迟在 14:02 升高,而磁盘图展示的是 14:05 之后的恢复过程,两者无法支持因果判断。指标平台与主机日志还应使用可对齐的时钟;请求内部的持续时间宜使用单调时钟计算,避免系统校时造成负耗时。先建立共同时间线,再解释关联。

3 剖析、跟踪与采样的取舍

剖析关注“时间或事件主要分布在哪些代码位置”,跟踪关注“具体发生了哪些事件、顺序和耗时是什么”,采样则是在部分时刻观察状态的采集方式。它们不是互斥的 3 个工具类别:剖析可以通过采样实现,跟踪数据也可以汇总成分布。选择时先问希望排除什么假设。怀疑程序在重复计算,适合看 CPU 调用栈的分布;怀疑文件操作阻塞,适合看有关系统调用的持续时间;怀疑请求在进入处理函数之前排队,则需要服务入口和工作线程之间的时间标记。

采样类似定时给运行状态拍照。某段代码在样本中出现得越多,说明在当前采集条件下它占据的相应活动越多。CPU 采样常能找到执行热点,但不能自然解释程序为什么睡眠了 800 ms。没有采到某个函数也不等于它从未执行,短暂、偶发的事件可能被漏掉。提高采样频率通常能获得更多样本,同时增加采集、存储和处理成本;真正的收益还取决于问题持续多久以及事件是否具有周期性。

跟踪可以显示某次 openat 返回了什么、某次读取持续多久,以及失败后是否立即重试。它适合验证明确假设,但记录事件本身可能扰动运行,尤其是系统调用非常频繁的进程。strace -f -tt -T -p 1234 -o trace.log 可以作为受控环境中的短时观察示例:-f 跟随相关任务,-tt 记录时间,-T 显示调用耗时。附加权限、输出规模及目标开销应提前确认;不要在繁忙生产进程上无期限采集。

还要分清“调用耗时”和“CPU 执行时间”。某个读取调用持续 300 ms,期间进程可能大多在等待。对跟踪记录中的耗时求和,也可能因为多个线程并行等待而大于墙钟时间。遇到这种情况不能认定工具算错了,应回到统计单位:每线程、每进程、每请求,还是整机。一个好习惯是在每张图旁写明采集事件、时间窗口、对象和单位,避免把不同含义的数据叠在同条证据链里。

观测工具选择取决于希望回答的问题和可接受的开销
观测工具选择取决于希望回答的问题和可接受的开销

观测本身也是实验条件。先使用已有指标和短时、低成本的观察,再根据假设增加细节。采集前记下响应延迟,采集中检查是否明显变差,结束后确认采集已停止。调用参数和文件路径可能包含敏感内容,保存与分享时应按实际需要裁剪。这里先掌握指标、调用栈和有限范围跟踪的用途;更深入的内核观测机制留到后续学习,不需要先理解它们才能完成有效调查。

4 动手:用一次火焰图定位热点

准备 1 个可重复运行的文件索引工具:它遍历固定目录,读取文件名和内容,生成本地索引。用户反馈最近处理相同目录明显变慢。先固定输入目录的快照、程序版本和启动参数,把结果输出到单独目录,避免下次遍历又把输出当成输入。使用 /usr/bin/time -p ./file-index ./fixture 记录总耗时、用户态 CPU 时间和内核态 CPU 时间。输入规模也要记下,例如 12000 个文件、合计 800 MiB,否则“快了 2 秒”缺乏比较基础。

先正常运行几次,确认症状稳定,并用进程统计判断它是否主要消耗 CPU。假设正常任务耗时约 12 秒,CPU 时间与经过时间接近,进程确实长时间忙碌,就可以采集 CPU 调用栈。若实际观察到大部分时间都在等待,应该调整假设,不能为了完成火焰图练习而强行把等待解释成计算。本节命令要求系统已安装 perf,且环境允许采集对应事件;权限受限或符号不完整时,应在获准的测试环境准备条件。

下面用软件事件按频率采集用户态 CPU 调用栈。使用带有符号信息、保留帧指针的构建,通常更容易得到可读栈;构建选项应与对照版本一致。任务很短时可扩大测试输入,避免只采到启动阶段。命令里的 99 表示目标采样频率,不代表每个窗口都恰好得到 99 个有效样本。

perf record -e cpu-clock:u -F 99 --call-graph fp -o s30-perf.data -- ./file-index ./fixture
perf report --stdio -i s30-perf.data
perf script -i s30-perf.data > s30-stacks.txt

perf report 可以先帮助确认热点和符号是否可读。若大量条目为未知符号,或者调用栈明显断裂,先修正采集与符号条件,再谈归因。需要生成 SVG 火焰图时,可使用事先安装、来源已确认的 FlameGraph 脚本,把 perf script 输出折叠成栈,再渲染。下列路径只是本地工具安装位置示例,不要求在线下载或执行未知脚本。

/opt/FlameGraph/stackcollapse-perf.pl s30-stacks.txt > s30-folded.txt
/opt/FlameGraph/flamegraph.pl s30-folded.txt > s30-flame.svg

火焰图中,横向宽度代表样本占比,纵向表示调用层次。横轴通常按调用栈排列,不是从左到右播放的时间线;颜色通常也不代表耗时大小。宽大的父函数包含子调用的样本,不能把父子宽度相加。阅读时从较宽的栈开始,看顶部正在执行的函数,再沿下方找谁调用它。先确认采集口径是用户态 CPU,便不会把图上 40% 的宽度误写成“总响应时间的 40%”。

从采样到火焰图,再把热点转成可验证的改动
从采样到火焰图,再把热点转成可验证的改动

假设图中字符串规范化函数占据约 38% 的样本,沿调用链发现每个文件名被重复规范化 3 次。接下来检查代码和输入,提出“小范围复用规范化结果”的假设。先确保结果仍一致,再对相同负载重跑。热点只是调查入口:它可能处理了最多的有效工作,也可能包含重复操作。只有当调用关系、代码行为和对照实验相互支持,才可以说找到了值得改进的原因。不要因为某个函数最宽就直接重写它。

练习的收尾是保存输入说明、原始数据、生成命令和实验结果。报告可以写成:“在固定目录与相同构建条件下,重复规范化占用户态 CPU 样本约 38%;减少重复后,经过时间中位数由 12.1 秒降到 9.4 秒,输出校验一致。”这仍不等于所有生产请求都能改善同等比例,后续还要覆盖不同文件大小、目录层次与并发条件。

5 基线、回归与对比实验

基线是对明确条件下行为的记录,不是永远正确的参考数字。至少写下程序版本、主机资源、输入规模、并发数、请求类型比例和缓存状态。读取 1 GiB 的少量大文件,与读取合计 1 GiB 的大量小文件,文件系统访问模式可能差别很大。把这些条件藏在“使用同样的数据”里,别人就很难复现。对网络服务,还应记录客户端所在位置、连接是否复用、超时以及重试设置。

区分冷启动与稳定运行。第 1 次读取可能触发更多实际存储访问,后续运行可能受益于缓存;程序启动时也可能创建线程或载入配置。可以把冷启动耗时和预热后的处理耗时分别报告,但不能拿旧版本的冷启动结果与新版本的预热结果比较。练习中不必为了追求“冷”而清理共享主机的系统缓存,使用独立测试环境和明确的实验口径通常更可靠。

对比实验尽量只改变 1 个因素。例如保持相同输入、相同主机和相同并发,只改规范化结果是否复用。每个版本运行 5 次,保留每次结果,并交替执行旧版与新版,减少主机逐渐升温或后台任务变化造成的偏差。可以报告中位数和范围;若 5 次结果差异很大,就先调查波动来源。不要在结果不理想时只保留最快的那次,也不要认为重复次数增加就能消除所有系统性偏差。

吞吐和延迟应一起看。服务在并发数为 8 时可能轻松完成任务,在并发数为 64 时仍能维持完成速率,却开始大量排队。如果压测客户端总是等上次完成才发下次请求,服务变慢时它也会自动减少发包,容易低估固定到达流量下的排队风险。因此测试报告必须说明是控制并发还是控制到达速率,并同时记录实际到达、完成、失败和超时数量。压测端也要有足够资源,否则测到的可能是客户端上限。

公平对比需要固定条件、重复测量和完整结果
公平对比需要固定条件、重复测量和完整结果

回归表示在约定指标上退化,既可能来自代码,也可能来自环境。新版本变慢时,先检查依赖、输入和主机条件是否一致,再缩小改动范围。性能差异小于日常波动时,不宜宣布成功或失败;可以增加代表性负载、延长窗口,或先报告“证据不足”。如果 CPU 时间下降而墙钟时间不变,可能只是把限制移到了存储或等待上。这是有用发现,但不能直接当成用户体验已改善。

实验还必须验证正确性。更快的索引若漏掉无读取权限的文件而不报告,或网络服务通过提前返回空结果减少耗时,都不构成等价优化。性能报告应把结果一致性、错误率、资源变化与延迟放在一起。预先定义可接受变化,例如“p99 不超过基线的 1.1 倍且错误率不增加”,能减少看到结果后随意解释的空间;阈值的选择则应来自服务目标和已有波动。

6 常见坑:过早优化、指标与用户体验脱节

过早优化最常见的表现,是还没有稳定症状就开始修改熟悉的代码。有人看到循环便改写循环,看到文件读取便加入缓存,看到网络请求便增加并发。每个动作都可能有用,也都可能增加复杂度或引入新等待。先问这段工作占整个任务多少。如果某段代码只占总时间的 5%,即使把它完全消除,理想改善也只有 5%。这个上界能帮助我们避免把大量时间花在低影响位置。

指标与体验脱节往往来自统计边界。服务端只记录进入处理函数之后的耗时,就漏掉任务队列等待;只记录已完成的请求,就可能漏掉断连与超时;只展示平均值,就会掩盖少量长等待。对于 shell 工具,只看主进程 CPU 时间也可能漏掉它启动的子进程。调查时应明确谁在计时、从何时到何时、失败是否纳入,以及取消后工作是否继续。相同名称的“延迟”未必具有相同含义。

另一个坑是把相关当因果。发布后 p99 与磁盘读取同时上升,可能是新版增加了读取,也可能恰好有备份任务运行,还可能是请求类型改变。可以通过相同负载下切换版本、暂时隔离后台任务或比较具体请求路径来排除解释。每次只改变有限条件,并记录预测:如果假设成立,哪项指标应该改善,哪项应基本不变。没有预测的试改很容易演变成碰运气。

观察窗口也会制造错觉。1 分钟平均 CPU 可能把 2 秒的尖峰冲淡,整机统计可能把某个核心的拥塞稀释。反过来,只截取最忙的 1 秒又会夸大日常影响。合理做法是先确定用户出现问题的时间,再用相应粒度查看资源与请求。不同来源的分位数不能直接求平均得到总体分位数,若要汇总多个进程或时间段,应保留原始样本或能够合并的分布计数。

最后,不要用增加重试掩盖失败。重试会增加实际工作量,在已拥塞的系统中可能进一步加长队列。改大超时也不会自动缩短处理时间,只会让调用方等待更久。真正的改善应体现为用户等待减少、失败受控、资源成本可解释。对于偶发的路径不存在、权限拒绝或连接失败,应先处理错误原因;让错误更快发生与让请求正确完成,是不同的结果。

把调查记录写得可被否证,是避免这些坑的有效方法。不要写“应该是磁盘问题”,而写“同个请求的读取阶段占 820 ms;若读取排队是主因,隔离后台扫描后,队列与读取耗时应同时下降”。这样的句子告诉下次接手的人该观察什么,也让团队能在证据不支持时及时换方向。

7 案例:CPU 不高但尾延迟很差

某台 8 个逻辑 CPU 的主机运行文件预览服务。服务从本地目录读取文档片段,再通过网络返回。稳定负载下每秒到达约 120 个请求,平时 p50 为 25 ms、p99 为 140 ms。定时目录扫描启动后,p50 变化不大,p99 却升到 1.8 秒,CPU 平均使用率只有 18%。这时“CPU 还有余量,增加工作线程”是未经验证的判断。用户等待可能发生在计算以外,也可能只影响少量特定请求。

先确认请求统计没有口径变化:客户端超时仍计为失败,服务入口记录到达数,服务出口记录完成数。按请求标识关联入口、开始处理、文件读取开始、读取结束和响应结束。检查后发现慢请求的队列等待通常不到 20 ms,而读取阶段经常超过 1 秒。将文件按大小和目录分组后,发现尾部请求集中在扫描任务同时访问的目录。这把调查范围缩到共享存储访问,但还没有证明扫描就是原因。

接着在相同窗口观察主机。pidstat -d -p 1234 1 10 显示服务存在读取活动,iostat -xz 1 10 显示相关设备的平均请求耗时与队列相较基线明显增加,同时目录扫描进程有持续 I/O。这里的设备指标只能说明这段窗口存在等待,不能证明每个慢请求都在等该设备。请求阶段耗时提供了应用侧证据,设备与进程统计提供了资源侧证据,两者对齐后,才形成较完整的解释。

低 CPU 的尾延迟调查从请求阶段逐步收窄到共享资源
低 CPU 的尾延迟调查从请求阶段逐步收窄到共享资源

在测试环境中保持服务版本、到达速率和文件集合一致,分别运行有扫描与无扫描的窗口,并交换顺序重复。若扫描暂停后读取阶段 p99、设备队列和总体 p99 都明显恢复,而错误率未增加,假设就得到支持。若总体 p99 不变,则还要检查其他等待。不能只凭“暂停扫描后 CPU 下降”宣布定位完成,因为最初要解释的是用户尾延迟。

改进可以从错开扫描时间、限制扫描并发、减少重复读取入手,每次只选取可验证的改动。单纯增加服务线程可能让更多读取同时进入设备,增加排队;缓存可能减少读取,也可能带来陈旧内容与额外内存需求。选择方案时应同时看新鲜度要求、资源成本和实现复杂度。最终保留相同请求集合的对比结果,确认原先最慢的目录组确实改善,而不是统计样本换成了更容易处理的请求。

如果请求阶段记录显示长时间耗在连接或响应发送上,调查就应转向网络路径。可以用 ss -tinp 查看相关 TCP 连接及收发队列线索,用 ip -s link show dev eth0 查看指定接口计数;接口名应替换为实际名称,并比较窗口前后的增量。发送队列持续积压可能与对端读取慢或路径传输受限有关,单次非零并不等于丢包。至于重传、往返时间和发送节奏如何互相影响,留到 S31 展开。

这个案例的结论不是“CPU 低就查磁盘”,而是先分解用户等待,再选择能够证伪假设的资源观测。若慢在处理前,就检查排队与工作线程;若慢在文件读取,就检查读取与共享资源;若慢在网络阶段,就沿连接和路径继续看。这样得到的方法才能迁移到 shell 脚本、日志归档和其他真实运维任务。

8 把观测闭环写进发布门禁

性能分析如果只在事故后启动,每次都要重新找基线、补计时、猜最近变化。发布门禁的目标是让这些证据在变更前后持续存在。门禁至少包含服务目标、代表性负载、基线版本、判断窗口和失败后的动作。对文件预览服务,可以选择覆盖小文件、大文件与热点目录的固定集合,以约定的到达速率运行,检查正确性、错误率、p95、p99 和完成速率,再查看 CPU、内存与存储等待是否出现异常变化。

门禁阈值不能脱离样本量。每个窗口只有几10个请求时,用 p99 的小幅变化直接阻止发布通常不可靠。应设置最小样本量和运行时长,对超时完整计数,并通过历史实验了解正常波动。存在稳定绝对目标时,可以同时检查绝对值和相对基线,例如既要求 p99 小于约定的 300 ms,也要求相较基线没有超出已允许的退化幅度。这里的数字只是示例,不能直接复制为所有服务的标准。

测试环境通过后,实际发布仍需要观察。先让有限范围的新实例处理可比较的流量,再在相同窗口对比旧版本与新版本。分流方式会影响结论:如果新版本收到的都是小文件请求,延迟更低并不能说明性能更好。应按文件大小、请求类型和关键路径分组,同时查看总体影响。版本、配置和依赖变更必须标记在同条时间线上,否则仪表盘上的突然上升很难归因。

观测闭环还要规定谁负责行动。触发门禁时保留版本、时间、负载与指标链接,先确认是否为环境异常,再决定停止扩大流量、回滚或继续调查。回滚应有明确的操作步骤和权限安排;数据格式、缓存内容或配置不兼容时,恢复旧进程未必立即恢复行为,需要在发布前验证可回退条件。门禁的意义是给团队提供可执行的决策,而不是生成无人处理的告警。

基线、发布、观测、决策和复盘组成闭环
基线、发布、观测、决策和复盘组成闭环

工具链可以很朴素。脚本负责启动负载、收集结果和输出退出码,流水线负责根据事先约定的规则停止推进,负责人查看原始证据。若用 shell 管道汇总结果,应确认前段命令失败不会被末段成功掩盖,并保留必要的原始日志。不要让统计脚本在没有数据时输出 0 ms 并判为通过;缺少关键观测本身就应标成无法判断。

每次性能回归解决后,把有效的场景加入下一次基线,把有区分力的指标加入日常观测。若本次发现读取阶段缺少计时,就补上阶段边界;若发现定时扫描影响尾延迟,就让代表性测试包含这类并行工作。这样门禁会逐步覆盖真实失败模式。入门阶段不追求收集所有事件,而是保证每项检查都能回答“这次变化是否让用户等待或失败变得更糟”。

9 从主机性能走向 TCP 深入(S31)

沿主机路径分析之后,仍可能遇到这样的证据:服务已完成计算与文件读取,响应却迟迟没有被客户端接收;或者同台主机访问很快,跨主机访问明显变慢。这时要把观测边界从进程扩展到连接与网络路径。不能仅因 CPU、内存和磁盘都正常就宣布“肯定是网络”,因为应用缓冲、任务排队或对端处理也可能位于当前计时范围之外。先补齐边界,再决定下一层需要什么证据。

可以做 1 个最小检查:在相同客户端、相同目标和相同响应内容下,记录连接与请求各阶段耗时。对于允许测试的 HTTP 地址,下面的命令输出连接完成时间、首字节时间和总时间;它们均从本次传输开始累计,不能直接当成彼此独立的阶段长度。使用域名时,连接时间还可能包含名称解析,HTTPS 则另外涉及安全握手,解读时要说明条件。

curl -sS -o /dev/null --connect-timeout 3 --max-time 10 \
  -w 'connect=%{time_connect} first_byte=%{time_starttransfer} total=%{time_total}\n' \
  http://127.0.0.1:8080/health

本机健康检查只能验证这个入口的有限行为,不能代表真实文件读取、跨主机路径或大响应传输。替换为真实测试路径时,要固定响应内容与认证条件,避免反复请求造成额外负担。再结合 ss 的连接状态与队列、接口计数增量,以及服务端的请求阶段时间,判断等待更接近建立连接、等待服务响应,还是传输响应内容。先把现象分开,才能学习合适的 TCP 概念。

S31 将进一步解释可靠传输为何需要确认、为何会重传,以及往返时间如何影响数据发送。当前只需保留正确的观察习惯:发送调用完成不代表对端应用已经消费数据,某次连接成功也不代表整个请求路径持续健康。连接、传输和应用处理各有边界,后续知识会帮助解释这些边界之间的等待,而不是替代本课的实验方法。

进入下一课前,可以整理 1 份交接记录:客户端与服务端位置、发生时间、请求大小、成功与超时数量、各阶段耗时、相关连接状态、主机资源概况和已经排除的假设。记录中明确“已观察到”和“尚未确认”,例如已观察到发送队列持续增长,但尚未确认是对端读取慢还是路径受限。带着可检验的问题学习 TCP,会比从协议名词直接猜故障原因更有效。

放进方案里

在方案中新增“性能目标与观测闭环”部分,先写清用户动作与边界。例如文件预览从客户端发起请求到收到完整响应计时,规定代表性文件大小、请求类型比例和到达速率,同时统计成功、失败与超时。用已有数据确定正常波动,再填写延迟与完成速率目标;不要只写“响应快、CPU 低”。明确目标适用的主机资源、数据规模和网络位置,避免验收时临时更换条件。

列出请求路径上的计时点:入口、开始处理、文件读取开始与结束、响应结束,并使用可关联的请求标识。服务侧保留 RED 指标,主机侧按 USE 选择 CPU、存储与网络线索。注明统计窗口、单位和采集开销,约定关键观测缺失时不能判为通过。日常使用低成本指标,发生异常后再短时采样或跟踪,并由负责人保存与问题有关的原始证据。

为性能变更安排对比实验:固定版本以外的条件,区分冷启动与预热,多次运行并保留完整结果。除延迟外,必须验证输出一致性、错误率和资源成本。写明当前假设、预期改善的阶段及反证条件;若差异处于正常波动范围,就记录证据不足,继续缩小实验范围。这样评审者能判断改动是否解释了真实等待。

最后把同套检查接入发布:预发布执行代表性负载,小范围发布后对齐新旧版本窗口,满足样本量与阈值才扩大流量。明确停止推进和回滚的触发条件、执行人及恢复验证方式。发布失败时保留时间线、版本与分组结果,复盘后将真实故障场景补入基线。验收材料应能回答用户是否更快、失败是否受控,以及发生退化后谁能依据什么证据采取行动。

10 小结:下一步 TCP 深入(S31)

性能分析从可验证的问题开始,用 RED 描述用户影响,用 USE 检查资源,用适合的问题选择剖析、跟踪或采样,再通过公平实验验证因果。火焰图提供热点线索,基线给出对照条件,发布门禁让有效证据持续发挥作用。

离开本课前,试着解释 3 件事:为什么 CPU 不高仍会出现长等待;为什么 CPU 火焰图的宽度不能直接代表请求总耗时;为什么版本变快仍需要检查错误和超时。如果能够把回答落到明确的计时边界和对照条件上,就可以带着连接、传输与对端等待的问题进入 S31。

同阶段相关课

AI 答疑

默认关闭。启用后,只发送本课标题、最近阅读的屏幕内正文摘录(最多 6000 字)与本次问题。

配置自己的服务