13.01 问题定义与利益相关者:不能丢消息到底要保证什么
返回第十三卷 · 当前 HTTP 合同:09.02 · 关键用户旅程:11.01 · 长期离线与权威:07.12
13.01 问题定义与利益相关者:不能丢消息到底要保证什么
DeepTutor 八节初稿经技术与教学审阅后的静态课程。人物、消息、离线时长、目标时间和失败事件均为虚构纸上案例;没有运行 Go、IM、数据库、压测、部署或站点。当前 S2
/v1合同仍是正文非空且最多 6 UTF-8 B、原始 HTTP 请求正文最多 4096 B、同 ID 重复 409、非成员隐藏 404、成功200 accepted_in_memory只表示本进程内存受理。未来 S3/v2的stored_in_teaching_db是提议且仍为 6 B,R9 的 6→9 B 待审。下文m-9/seq9/E9只用于讨论未来设计,不能写成当前已运行能力。09.02 当前合同
一、“发送成功后不能丢”含了几个尚未回答的问题
假设产品同学说:“A 发给 B 的消息显示成功,B 离线 25 小时回来后不能丢。”初学者容易立刻想到“上 Kafka”“加三个副本”,但这些是候选做法,并未说明哪一次动作构成“发出”、谁看到“成功”、B 何时算“找回”、丢失的后果是什么。问题定义先写可观察的用户场景,再谈技术选项。Google SRE:关键用户旅程
| 原句中的词 | 需要追问的可观察含义 | 当前可说的事实 |
|---|---|---|
| “A 发出” | HTTP 请求进入、服务返回、消息入权威存储各是哪一步? | S2 /v1 的 200 只表示本进程内存受理 |
| “成功” | A 页面显示、DB 已存、事件可重放、B 设备 ACK、B 已阅读? | 这些不是同一个确认点 |
| “不能丢” | 是重试去重、进程重启、长离线补拉,还是旧设备同步? | S2 没有提供持久与离线恢复承诺 |
| “B 离线 25h” | 从哪个时间戳算?哪台设备?B 是否仍为成员? | 需定义可补拉资格与窗口 |
| “回来” | 登录成功、网络重连、取得新游标,还是 UI 可见? | 需给测量起点和终点 |
比如当前 m-a 的 /v1 200 若发生在 S2,只说明接收进程受理,进程更替后的状态还没有权威保证。若需求真是“B 25h 后按权限找回”,它将要求未来的权威历史、权限检查与补拉路径,不能悄悄改写现有 200 的意义。问题定义要直接写出现状与目标的缺口,否则后续团队会对“成功”各用自己的解释。09.05 数据访问边界 · 11.01 确认点
二、沿用户旅程识别谁受影响、谁有决定权
把纸上旅程按时序画成六步:A 向会话 c-a 发送 m-9;未来候选方案若建立权威 DB,消息得到 seq9;从权威状态派生稳定事件 E9=evt:m-9:v1;B 的设备离线;B 约 25h 后重连,从有成员权限的权威历史找 seq9 缺口;设备最后确认或展示消息。这条旅程是未来需求草图,不是当前 S2 的执行路径。教学 broker 若只保留 24h,B 25h 后不能仅靠它重放全部缺口。07.12 权威与补拉
| 利益相关者 | 想要的结果 | 可能的冲突/决定 |
|---|---|---|
| A:发送者 | 明白 200 到底承诺哪层,不因重试制造两条意图 | 可能希望立即显示“已送达”,但当前确认不足 |
| B:接收者及多设备 | 重连后有权按序补缺,旧设备不重复扰乱 UI | 需要定义设备 ACK、游标和离线窗口 |
| 会话其他成员/管理员 | 成员变更后不越权读取历史 | 可见范围与“旧消息继续可见”规则要定 |
| 产品/客服 | 能解释成功、迟到、失败及用户补救路径 | 不能以一个后台队列指标替代用户结果 |
| Go 后端/数据团队 | 有明确权威来源、幂等键与一致性目标 | 需估写入、迁移、保留、查询与重放成本 |
| 客户端/兼容负责人 | 旧版理解当前 6 B/409/404/200 | R9 和 /v2 不得伪装成旧合同 |
| 值班/平台/安全/成本负责人 | 知道告警、回退、访问控制、保留与容量责任 | 更长保留和更多副本有成本与隐私影响 |
“利益相关者”不等于所有人都批准每个细节。应记录谁提供用户证据、谁决定业务承诺、谁验证实现可行、谁接受成本和运行风险。若产品想让 A 看到“已送达”,但客户端团队只测到服务端 200,须把分歧带回确认点定义,不靠会议纪要中的“成功”二字掩盖。10.01 可验证需求
三、把目标、非目标、约束、假设和方案分开
同一句需求里可能混着五种性质。目标是用户/业务希望得到的结果;非目标说明本轮明确不承诺什么;约束是已生效的合同或外部限制;假设是尚缺证据、可以证伪的事实判断;方案是为达目标可比较的做法。把它们写在不同格子里,后续才能改变方案而不悄悄更改目标。SEI:质量属性需求
| 类别 | 本例纸上写法 | 需谁确认/验证 |
|---|---|---|
| 待审目标 | “有权的 B 离线 25h 后重连,仍能按 seq 补到 m-9” | 产品、客户端、数据与安全 |
| 非目标 | 本轮不把“B 已阅读”当“服务端已存”;不自动批准 9 B | 产品与协议负责人 |
| 当前硬约束 | S2 /v1 的 6 B、409、404、200 内存受理语义;R9 未批 | 以现有合同验收 |
| 待验证假设 | B 25h 的离线是否常见;成员撤销后旧历史可见规则为何;DB 保留/容量如何 | 用户数据、权限评审、容量实验 |
| 候选方案 | DB 权威历史、延长 broker 保留、补拉协议等 | 后续再按目标、成本和故障比较 |
“使用 Kafka”“三副本”“单聊消息存 30 天”都不能仅凭这句话变成要求。broker 保留期改长或许缓解某个窗口,但仍要核权威性、权限和跨客户端游标;三副本或许改善进程存活,却不能把 S2 内存受理改成已持久化。相反,成员权限是所有候选方案都不能绕过的约束:B 是否可读要按已明确的成员和历史可见规则判断。未知规则应标记待决,不能替产品或安全负责人拍板。07.12 跨系统一致性 · 09.07 授权
四、用确认点和反例写出可验收的业务语义
一次消息旅程可有多个确认点,它们回答不同的问题。当前 S2 只明确 A 的本进程受理;未来 S3 候选要求 DB 权威存储,之后还有事件传递、B 设备获取/确认、用户阅读。一个阶段的“成功”不能自动升级成下一阶段。11.01 业务测量
| 纸上观察 | 可说的结论 | 不得偷换成 |
|---|---|---|
当前 A 收 200 accepted_in_memory | 本进程受理 m-a | DB 已写、事件已留、B 已收到 |
未来 S3 返回 stored_in_teaching_db | 提议中的教学 DB 存储边界 | 设备收到、已阅读或 9 B 获批 |
| 未来派生 E9/P0 offset42 | 某事件路径有记录 | B 25h 后必从 24h broker 补全 |
B 客户端 ACK seq9 | 指定设备按未来协议定义的接收处理边界给出确认 | B 真实阅读、UI 已展示或其它设备均完成 |
验收要覆盖顺利路径和有意义的反例:同 ID m-9 重试若仍在当前 /v1,应按 409 而非“同正文即可幂等 200”;非成员发送/补拉应按相应授权规则拒绝,当前发送合同隐藏为 404;7 B 正文仍超过当前 6 B 限制,不能借未来 R9 提议放行。未来候选还要试网络超时后 A 不知结果、权威写入后事件失败、B 离线 25h、成员在离线期间撤销、旧客户端只认识旧响应等。每个反例都写观察、期望、尚未决定的规则,不能把未决成员历史可见性写成测试必过事实。09.02 当前合同 · 09.10 协议兼容
五、把“可靠”改写为六段质量属性场景
“可靠、快、可扩展”都是方向,无法直接验收。SEI 的质量属性场景可拆为刺激源、刺激、环境、受影响对象、响应、响应度量六项;“响应度量”回答测试时如何判定达标。下面只是待审提议,用于练习如何提出问题,并非现有 SLO 或产品承诺。SEI:Quality Attribute Scenarios
| 六项 | 虚构的长离线场景 |
|---|---|
| 刺激源 | B 的一台合法设备 |
| 刺激 | 设备离线 25h 后凭已有身份重新连接,请求 c-a 在旧游标后的历史 |
| 环境 | A 的 m-9/seq9 已在未来候选的权威 DB,教学 broker 只留 24h;B 的成员资格规则已获确认 |
| 受影响对象 | 补拉 API、权威历史及客户端游标 |
| 响应 | 先授权,再从权威历史按序返回可见缺口;重复重试不造第二条消息意图 |
| 响应度量 | 纸上候选:符合资格的请求自重连请求开始至客户端取得 seq9 不超过 120 秒;资格、采样、失败分母和目标比例仍待评审 |
这里 25h>24h 只排除了“仅凭这段 broker 保留期覆盖全离线窗口”的推断,不能单独证明 DB 补拉方案性能。若要把 120 秒变成目标,须决定网络条件、设备类型、消息量、时间起点、超时与拒绝是否计入分母,并取得产品/值班/成本负责人的同意。可靠性还可有其它场景,如 Node 故障、重复投递、非成员探测和旧客户端升级;每项都要用具体刺激与响应说明,不能用“99.99% 可靠”覆盖所有用户旅程。Google SRE:用户中心 SLI
六、用证据和失败成本排序,不把纸上数字当生产事实
问题简报要记录每句话的证据类型。当前 /v1 合同可从课程规范核;固定 OpenIM 源码只支持所读边界;“多少 B 会离线 25h”需用户行为分布;“120 秒是否可行”需在明确的未来实现与负载下实验;“历史应留多久”需业务、合规、成本共同决定。先列证据缺口,再定最小取证动作,而不是为已经喜欢的方案挑指标。11.02 分布与长尾
| 问题 | 当前证据/缺口 | 下一步最小验证 |
|---|---|---|
| B 长离线需求多大? | 只有一个虚构 25h 例子 | 按设备和会话统计真实离线分布、客服反馈;注意样本/隐私 |
| A 认为何时成功? | 当前 200 文义已定,但 UI 文案/用户理解未知 | 对照客户端文案与用户访谈,标出误解位置 |
| 补拉能否有权、按序完成? | 未来 m-9/seq9 是纸上模型 | 定成员历史规则与测试数据,再做隔离验证 |
| 哪种失效代价最高? | 有待估用户信任、值班恢复、存储和隐私成本 | 让产品/客服/安全/值班分别给案例与边界 |
排序时同时看影响范围、发生频率、恢复难度、证据不确定性和实现/运行代价。少量但不可恢复的历史缺口可能比大量可重试的慢请求更紧急;平均离线时长可能掩盖超过 24h 的尾部用户。若数据暂缺,就将“长离线占比未知”放进决策风险,不把本章 25h、24h 或 120 秒包装成生产测量。Google SRE:SLO 以用户旅程为中心
七、交付一页问题简报,让下一章有可比较的输入
一份最小问题简报应能让没有参加口头讨论的人回答“为什么做、谁受益、哪里是现状、何事算通过、什么仍未知”。可按下面七栏完成,审阅人对每一项给“已知/待验证/待决”,而不是只能在末尾签名。10.01 可验证需求
| 简报栏位 | 本例应该写的内容 |
|---|---|
| 使用者与旅程 | A 发送、B 离线重连、旧端展示、成员权限与值班恢复 |
| 当前事实 | S2 200 仅进程内存受理、6 B/409/404;未来 m-9 不是已运行 |
| 待审目标/非目标 | B 25h 后有权补 seq9;本轮不宣称“已阅读”,R9 不借机生效 |
| 约束/假设 | 旧端兼容、成员历史规则、broker24h 与 DB 权威可行性均标状态 |
| 质量场景 | 六段写清 B 重连刺激、环境、响应与 120 秒纸上候选度量 |
| 失败成本和证据 | 用户可见缺口、客服/值班、存储/隐私成本,以及每项取证计划 |
| 验收与决定人 | 产品/客户端/数据/安全/值班谁同意目标,何时评估后续方案 |
后续可以比较“维持 S2 并清楚提示边界”“建立未来权威 DB 和补拉”“调整 broker 保留”等候选,但本章不预选。调整保留并不能自动解决谁是权威、成员授权、旧客户端和 200 的语义;即便选择 DB,也要审写入确认、派生事件、补拉、迁移和回退。固定 openimsdk/open-im-server 提交 f6411a8a1a31d3df36f4c2b3ad28481a94141e1f 的 send.go 选定路径调用 MsgToMQ 后返回;另一 Mongo 消费路径调用 BatchInsertChat2DB。两处不能证明完整生产 ACK、真实业务需求、设备送达或本课程未来方案。OpenIM 阅读地图
八、22 道分层练习:改写“不能丢消息”
先辨词义与角色,再写场景和反例,最后审问题简报。答案均基于本章纸上设定。
基础 1–8:术语与边界
1. “消息不能丢”为什么还不是可验收需求?
未定哪条消息、确认点、时间窗口、失败条件、用户可见结果与度量。
2. 当前 S2 `/v1` 的 200 保证什么?
accepted_in_memory 只表示本进程内存受理。
3. 未来 `stored_in_teaching_db` 能直接代表 B 已阅读吗?
不能。存储、设备 ACK 和阅读是不同确认点,且 S3 尚为提议。
4. 三副本、Kafka、30 天保留属于目标还是方案/参数?
是候选方案或可协商参数,不能替代用户目标。
5. 当前 7 B 正文可因 R9 提议而放行吗?
不能。当前上限仍为 6 UTF-8 B,R9 待审。
6. B、客户端团队和安全负责人为何都是利益相关者?
B 承受缺口,客户端负责展示/兼容,安全决定有权历史范围;三者影响需求与验收。
7. 目标与假设最简单怎样区分?
目标说期望用户结果;假设说尚待取证的事实或因果判断。
8. SEI 质量属性场景有哪六项?
刺激源、刺激、环境、受影响对象、响应、响应度量。
分析 9–16:旅程与反例
9. B 离线 25h、broker 保留 24h,可只凭 broker 补全吗?
不能保证覆盖全窗口;未来应审有权权威历史补拉及其成本/可行性。
10. A 重试同 ID,当前 `/v1` 应返回什么?
同 ID 重复按当前合同返回 409,即使正文相同。
11. B 在离线期间失去成员资格,能直接规定旧历史可见吗?
不能。需产品与安全确认成员历史规则,再据此写授权验收。
12. 纸上 120 秒从哪里算到哪里?
候选场景是从合资格设备发起重连请求,到客户端取得 seq9;分母/网络条件仍待定。
13. 网关记录 E9,能证明 B 的设备拿到 `seq9` 吗?
不能。事件记录与设备 ACK 是不同确认点。
14. 当前非成员向 `c-a` 发送,能用 403 暴露会话吗?
不能。当前发送合同要求隐藏为 404;未来历史补拉另需明确授权合同。
15. 只有平均离线 2h,就能忽略 25h 尾部吗?
不能。需要分布、用户影响和恢复代价,不能只看平均值。
16. 当前 S2 200 后进程故障,应写“权威消息丢失”吗?
不应。当前并无权威持久承诺;应按现行受理语义写用户可见影响和能力缺口。
决策 17–22:问题简报
17. 产品要把 A 页面改成“已送达”,先问哪层证据?
先确认是否有 B 指定设备 ACK/展示证据及其协议含义;当前 200 不足以支撑。
18. 延长 broker 保留期就满足全部目标吗?
未必。还需权威来源、权限、游标、旧端、故障和运行成本。
19. “B 25h 离线很常见”应放在简报哪一栏?
待验证假设;用实际离线分布和用户反馈核对,不能把虚构案例当统计。
20. 无法估计 120 秒目标可行性时怎样写?
标为待审候选度量,列工作量、依赖、样本与隔离实验,不宣称已有 SLO。
21. 需求优先级至少比较哪五项?
影响范围、发生频率、恢复难度、证据不确定性及实现/运行代价。
22. 一页问题简报必须使审阅人回答什么?
谁受益、现状与目标差在哪、哪些是约束/假设、如何验收、失败代价、谁决定以及哪些方案留后比较。
本章完成标准与后续路径
能把“不能丢”拆成具体用户旅程、角色与确认点,把当前 S2 事实与未来 S3/R9 提议分开,写出六段质量属性场景、反例、证据缺口和决定人,才算完成第一轮。下一章13.02 领域与状态建模将沿 u-a/u-b、设备、会话、消息和游标深入讨论身份与状态。