11.01 业务结果与测量:每个 IM 指标先写清分母和确认点
返回第十一卷 · 应用前置:09.01 · 请求链前置:09.04
11.01 业务结果与测量:每个 IM 指标先写清分母和确认点
DeepTutor 初稿经技术与教学审阅后的静态课程。所有时间、次数、比例和故障数据均为明确假设的纸上样本;本次没有运行 Go、IM 服务、网络实验、监控系统、性能基准或站点构建。
先问用户得到什么,再问系统有几个指标
09.01–09.04 已把 u-a 提交 m-a 到 c-a 的过程拆成:客户端发起、服务端本进程内存受理、未来才会有的持久保存、u-b 设备收到、用户已读。一次 200 accepted_in_memory 只覆盖第二步。若以后用户说“消息经常发不出去”,统计哪一步?用 HTTP 200 比例、队列长度、CPU 百分比、已读比例,会得到完全不同的答案。
本章先学测量合同:把用户动作、可观察事件、时间窗、分子、分母和单位写清楚,再计算比例与时延。当前课程项目仍只有本地 CLI 和静态在线 IM 教材,没有可运行的 S2 发送服务;即使“内存受理”这一级也没有真实线上样本。下文 u-a/u-b/c-a/m-a 与所有数字均为虚构,持久、设备和已读计数更是未来阶段的假想事件。
| 第一遍 | 第二遍 | 个人练习成果 |
|---|---|---|
| 用户动作、成功点、计数与单位 | 队列/事件时间窗、重试、延迟与资源口径 | 两张带分子分母的指标卡 |
11.02 才深入均值、分位数和样本分布;11.03 才讲日志、指标与 Trace 怎样采集;11.08 才把指标变成目标、错误预算与告警。这里不提前给真实生产 SLO,也不把纸上百分比当质量结论。
一、同一条消息有多个“成功”事件
先只看一个用户动作:u-a 在设备 A 点击“发送 m-a”。后续可能经历这些候选确认点:
A 发起尝试
→ 服务端内存受理(S2 教学成功点)
→ 持久条件满足(S3 才设计)
→ B 的某台设备收到(S5 才定义确认)
→ u-b 的阅读事件被记录(S5 的另一种业务状态)每一步的主体和证据不同。HTTP 200 可以作为“客户端收到本教学接口受理回应”的证据,但服务端内存受理本身可能已发生而 HTTP 响应丢失;设备收到要设备侧或协议确认,已读更依赖阅读事件定义。不能把这些数字相加,因为后面的状态通常是前面某些消息的后续发展,不是新的独立用户动作。
| 指标候选 | 最接近的用户问题 | 不能据此证明 |
|---|---|---|
| 本次请求得到 200 的比例 | 客户端能否及时看到受理回答? | 消息已写盘、已送达 |
| 内存受理比例 | 教学服务是否把合格尝试记入当前进程? | 进程重启后还在 |
| 持久比例 | 未来存储确认点是否满足? | B 设备已收到 |
| 设备收到比例 | B 的某设备是否确认收取? | u-b 本人已读 |
| 已读比例 | 定义的阅读事件是否发生? | 用户理解或同意内容 |
“成功”必须绑定动作与确认点。例如历史 GET 的 200 是查询响应,不能并入消息发送受理;GET 返回空 messages:[] 在查询范围和权限正确时仍可成功,但也可能因范围错而无法满足用户目标。接口状态与业务正确性要分别核对。
二、每个比例写四项:事件、单位、时间窗、分母
先给一个模板:
名称:合格发送尝试的内存受理比例
对象:一次已认证且有权在 c-a 发消息的请求尝试
分子:属于该组尝试、并在约定观察期限内完成内存提交的尝试数
分母:该组全部合格发送尝试数
时间:按尝试开始时间入组;每项再观察其后 60 秒
单位:无量纲比例,可写成百分比如果分母从“请求尝试”换成“唯一消息 ID”,指标含义已变;如果窗口从“请求开始时间”换成“事件实际到达时间”,也已变。记录数字前先写单位:请求/秒、消息/秒、连接数、字节、毫秒、CPU 秒/秒分别不是同一量。次数除以观察时长得到速率,例如 100 次尝试在 300 秒内开始,平均为 100/300≈0.333 次/秒,并不表示每一秒都均匀到达。
分母为 0 时比例没有可计算样本,应写“本窗口无合格尝试/未定义”,不能随意填 0% 或 100%。若只统计有合法凭据的请求,会把大量未认证或格式非法的访问排除在这个业务比例之外;这可能符合“合格调用成功率”的定义,但还需另记拒绝类别和总流量,避免把用户遇到的问题从仪表盘上悄悄删掉。
“服务器返回了错误”也不是一律系统失败:正确拒绝越权读取是安全行为;重复 ID 得到 409 可能是客户端重试产生的可预期冲突。若产品要衡量真实用户能否完成发送目标,需要明确定义哪些尝试算合格机会,哪些是输入错误、权限拒绝、重试,以及这些类别如何单独展示。不要为了让一个比例好看,在计算后临时改分母。
三、同一批尝试:四个下游比例怎样算
现在给唯一的一组纸上假设:在 [10:00,10:05) 这 300 秒内,虚构用户群发起 100 次合格且互不重复的发送尝试。每次从自己的开始时刻起观察 60 秒,最晚的尝试可在 10:06 左右完成归档。为便于入门,假设后续事件逐层包含:其中 92 次达到 S2 内存受理,80 次在未来系统里达到持久确认,70 次被目标设备确认收到,65 次有阅读事件。所有后续数值都是未来假设,不是当前课程服务的实际指标。
| 对同一批 100 次尝试的观察 | 计数 | 以全部 100 次为分母 | 不能读成 |
|---|---|---|---|
| 内存受理 | 92 | 92/100=92% | 92% 已送达 |
| 未来持久确认 | 80 | 80/100=80% | 当前 S2 已写数据库 |
| 未来设备确认 | 70 | 70/100=70% | 70% 用户已读 |
| 未来阅读事件 | 65 | 65/100=65% | 65% 用户理解内容 |
也可以问条件比例,但必须改名并写清新分母。例如“在已持久的 80 次中设备收到的比例”为 70/80=87.5%;它与“全部尝试中的设备收到比例 70%”回答不同问题。80/92≈86.96% 是内存已受理者中后来满足持久条件的比例;不能拿它跟 65/100 直接比较好坏。每个结果还要标注本题 60 秒的观察期限,超过期限才发生的事件不在该次计算的分子里。
起始队列窗口与事件发生窗口尤其容易混淆。这里的 100 由“发起时刻落在 10:00–10:05”定义;它们的设备确认可能在 10:05 之后才到。如果另一张仪表盘统计“10:00–10:05 实际发生的设备确认 70 次”,其中可能混入更早发起的消息,并漏掉本批稍后到达的确认,不能直接除以本批 100 得出同一口径的 70%。先关联消息身份和起始队列,再决定观察期限,才能复核分子确属分母中的对象。
四、请求尝试、唯一消息与重试不是同一单位
09.02 已给一个关键变式:u-a 的首次 POST m-a 在服务端内存提交成功,但 200 响应丢失;客户端看到超时,又以同一 ID 重试。本课程 S2 合同下,第二次请求可能得到 409 DUPLICATE_MESSAGE。这里有两次 HTTP 请求尝试、一个用户想发的业务消息、一次内存受理;不能把它们统称为“两条消息”。
| 问题 | 分母怎样取 | 得到的纸上结果 |
|---|---|---|
| 每次 POST 是否直接返回新的内存受理? | 2 次请求尝试 | 仅首次内存提交,1/2=50% |
| 这位用户想发的一条消息是否已在内存? | 1 个唯一业务意图 | 已受理 1/1,但客户端可能不知道 |
| 客户端是否得到清楚的成功回答? | 2 次请求或 1 次意图,需选一种 | 首次超时、第二次 409,不可直接记“已确认” |
上表只用于说明分母改变会改变问题,不建议把 1/2=50% 当作系统整体成功率。若重试时改用新消息 ID,服务可能把它当第二条不同消息;如果同 ID 但内容变化,服务又可能拒绝冲突。S5 才设计稳定请求身份、查询确认与幂等窗口。11.01 只要求在指标卡上明确“按尝试计”还是“按唯一业务消息计”,并对超时的未知结果保留单独类别。
还要防止把所有拒绝都塞进“服务器故障”。u-x 无权访问 c-a 而收到 404 隐藏回应,是按接口合同工作的安全结果;limit=0 被 400 拒绝说明输入错误;m-a 重试收到 409 表示已识别重复。这些都影响用户体验和调用方质量,但不等同于“服务没有可用 CPU”或“业务消息未曾受理”。按类别计数并给出用户影响,再决定哪些进入某个可靠性分母。
五、时延从哪刻开始,到哪个确认点结束
比例说“多少次满足条件”,时延说“每次花多久”。先在单一理想时钟的纸上模型里给一条消息时间线;真实 A、服务端、B 是不同机器,不能未经核对就直接相减它们各自的墙上时钟:
t=0 ms A 点击发送
t=12 ms 服务端收到请求
t=25 ms 服务端完成内存提交
t=40 ms A 收到受理响应
t=200 ms B 设备按未来协议确认收到
t=5000 ms u-b 的阅读事件被记录若都用题设同一时钟:客户端受理回应时延为 40−0=40 ms;服务端从收到请求到内存提交为 25−12=13 ms;设备确认相对点击为 200−0=200 ms;阅读事件相对点击为 5000 ms=5 s。不要把这四个数都叫“发送时延”,也不能把 40 ms 当作网络单向传播:它含客户端、服务端、两向网络及排队等阶段。
真正测量时,要在同一进程/设备用合适时钟算局部时长,并用关联 ID 将跨服务事件联起来;跨设备时间戳若有时钟偏差,直接相减可出现虚假的负延迟。04.01 的传输/传播/排队与 03.04 的 CPU 等待会进入不同阶段预算。若 A 从未收到响应,只能记超时、未知或到观测期限尚无确认,不能给它填 0 ms,也不能把超时值直接当成实际完成时延。分布、尾延迟和缺失样本的处理在 11.02 继续。
六、HTTP 状态、业务正确性、负载与资源分别记
再造一个独立于发送样本的历史查询纸上队列:50 次合格、授权的 GET 中,45 次收到 HTTP 200;对这 45 次进一步核对范围、分页、顺序和可见性,只有 42 次真正满足既定查询合同。那么:
HTTP 200 比例:45/50 = 90%
业务正确结果比例:42/50 = 84%差的 3 次可能是错误范围、游标跳项或权限过滤缺项;状态码 200 仍不能替它们证明正确。反过来,messages:[] 若对正确范围确实无可见历史,应计为成功;不能因“空”就给它标失败。若要追查这 3 次,必须保存脱敏的请求条件和独立预期,而不是凭响应里有无文字判断。
负载是系统被要求处理的工作,例如合格请求/秒、消息正文大小、活跃连接比例、群消息目标数。资源是完成工作可使用的 CPU、内存、描述符、网络、存储与队列空间。利用描述资源在某口径下用了多少,饱和描述可用能力跟不上而出现多少等待/排队,错误描述工作如何失败。它们相关但不互相代替:
| 观察 | 还要问什么 |
|---|---|
| 100 次发送尝试/300 秒 | 是否平均分布?重试占多少?每条多大? |
| 某段 CPU 平均 30% | 哪台机器、几个核、采样多久?是否单核热点或等存储? |
| 队列有 500 项 | 入队/出队速度、容量、最老等待多久? |
| HTTP 200 为 90% | 错误类别、剩余 10% 在哪层、200 中业务正确多少? |
03.04 已说明大量空闲连接不必占满 CPU,群聊扇出却可能带来可运行任务。CPU 低不能直接证明系统还有足够描述符、内存或下游吞吐;CPU 高也不能仅凭连接数解释。测量应同时记录负载构成和资源口径,后续 11.04 的诊断方法、11.07 的压测才可真正比较条件。
七、反例与当前 S2 的证据缺口
下面几句话看似像指标,实际上缺少关键前提:
- “HTTP 200 率就是设备送达率。” 09.02 的 POST 200 只承诺本进程内存受理;设备确认另有事件。
- “10:00–10:05 设备确认数 / 同窗口发送尝试数就是投递率。” 两组事件可能来自不同的消息队列,须按起始队列关联。
- “客户端没收到回应,所以本次受理失败。” 响应可能丢失,服务端可能已提交;应记未知并设计查验。
- “只看成功请求,成功率可达 100%。” 删除失败请求会改变分母,必须公开合格范围与排除项。
- “CPU 30%,容量还富余 70%。” 利用率的对象、核数和时间窗不清;其他资源或队列可先饱和。
- “跨两台设备直接减时间戳得到 200 ms。” 时钟可能不一致,需控制时钟误差或使用各端局部时长与关联事件。
- “没有请求时成功率为 0%。” 分母为零,比例未定义,应报告无样本。
当前课程仓库没有运行中的 HTTP/WS 服务、持久层、B 设备确认或阅读事件,因此不能实际采集本章这些比例。要让未来实验可核对,先设计不含正文与真实凭据的事件字段:虚构消息关联 ID、会话范围、请求开始、内存提交、响应尝试、目标设备确认及阅读事件的阶段标记;再确定保留期、隐私与关联方式。11.03 会教日志、指标和 Trace 的实现位置;本章只列证据需求,不伪造数据源。
八、交付两张指标卡,再做分层练习
一张发送指标卡应写:用户动作是合格发送尝试;开始队列按请求开始时刻入组;分母按请求尝试还是唯一消息需选定;分子可分别定义内存受理/未来持久/设备/阅读,观察期限和迟到事件处理必须明确;超时结果未知单列。另一张历史查询指标卡应写:授权 GET 的范围/分页/可见性预期,分母为合格查询尝试,分子为真正返回正确表示的次数,200 只作为一个阶段观察。
分层练习:先回答,再核对反馈
1. 发送的“成功”只有一个确认点吗?
不是。客户端回应、内存受理、持久、设备收到和已读分别有自己的证据。
2. 当前课程实际有在线 IM 的送达样本吗?
没有。本章所有线上事件与数字都是纸上假设。
3. 比例的分母为零时填 0% 合适吗?
不合适。应报告该窗口无样本、比例未定义。
4. 100 次尝试在 300 秒内开始,平均尝试速率?
约 0.333 次/秒,不表示每秒到达都均匀。
5. 92 次受理相对 100 次尝试是多少?
92%,只对题设同一队列和 60 秒观察期限成立。
6. 80 次未来持久相对全部尝试是多少?
80%;不是当前 S2 实测的数据库写入率。
7. 70 次设备确认相对全部尝试是多少?
70%,不能叫阅读比例。
8. 已持久 80 次中设备确认 70 次,条件比例是多少?
70/80=87.5%,分母已改,不等于全部尝试中的 70%。
9. 65 次阅读相对全部 100 次尝试是多少?
65%;仍需说明本题的阅读事件定义和 60 秒观察期限。
10. 起始队列窗口与事件发生窗口能直接相除吗?
不能。后续事件可能来自较早尝试或延迟到窗外。
11. 同一 m-a 重试两次意味着两条业务消息吗?
不一定。它可以是一个用户意图的两次请求尝试。
12. 第二次返回 409,就能说第一次没有受理吗?
不能。本章 S2 可能正因第一次已受理才识别重复。
13. 客户端受理回应时延在题设中是多少?
40−0=40 ms,从 A 点击到收到回应。
14. 服务端收到请求到内存提交是多少?
25−12=13 ms,不等于客户端端到端时延。
15. B 设备确认与阅读事件各相对点击多久?
题设为 200 ms 和 5000 ms=5 s,属于不同确认点。
16. 跨设备未校准墙钟能直接相减吗?
不能。可能有时钟偏差,需局部时长与关联证据。
17. 50 次 GET 有 45 次 200,HTTP 200 比例?
45/50=90%。
18. 其中 42 次结果正确,业务正确结果比例?
42/50=84%,低于单看状态码的 90%。
19. 正确返回 `messages:[]` 应计为查询失败吗?
不应。对正确范围确无可见项时,它是合法成功结果。
20. CPU 低就证明所有资源容量充足吗?
不能。队列、内存、描述符、存储或网络都可能先饱和。
21. 超时请求的完成时延可以填 0 ms 吗?
不能。它的结果未知或在观察期限内未完成,不是零时延成功。
22. 本章纸上比例能作为 OpenIM 或本项目实测 SLO 吗?
不能。没有运行数据,也尚未在 11.08 设定目标与观测实现。
来源与下一步
- Google SRE:Monitoring Distributed Systems与Workbook:Implementing SLOs:从用户结果定义可测量指标的资料入口。
- Brendan Gregg:USE Method:负载、利用、饱和和错误需分视角观察的后续参考。
- 09.01 应用确认点与09.02 HTTP 合同:本章例子的业务范围。
下一章11.02 分布与统计将从样本、均值、分位数和聚合误区继续。进入前先能为一个比例写出分子、分母、对象单位、入组时间与结果观察期限。