全栈应用灰度阶段验证什么 全栈应用灰度阶段验证什么全栈应用做灰度发布页面能打开只是起点。尤其是带流式检索、长连接和本地持久化状态的产品新旧客户端与新旧服务端会在一段时间内同时存在。发布设计若默认用户会刷新页面或默认 SSE 连接会立刻断开就很容易把兼容性问题留给少数已经上线的用户。灰度前先列出“会跨版本保存或传递的数据”HTTP 响应、SSE 事件、缓存键、localStorage/IndexedDB 中的会话记录、队列消息和链接里的参数。每项都要说明旧版遇到新增字段、未知事件或缺失字段时该怎样处理新版读取旧数据时又该怎样迁移。这样做比用流量比例替代验证更有效。数据契约要允许渐进演进将citations从字符串数组改成对象数组看起来像普通重构实际上会同时影响序列化、渲染和本地缓存。最安全的选择通常是新字段与旧字段并存一段时间或者让服务端返回一个兼容的规范结构。什么时候删除旧字段应由活跃客户端版本和迁移完成情况决定而不是固定等几天。前端运行时校验可以防止一段异常数据直接打断渲染但它不是许可服务端随意变更协议。校验失败时要记录不会泄露内容的诊断信息并把对应模块置为可解释的降级状态不能悄悄吞掉所有错误否则协议回归很难被发现。type Citation { id: string; title: string } function readCitations(value: unknown): Citation[] | null { if (!Array.isArray(value)) return null const result: Citation[] [] for (const item of value) { if (typeof item string) result.push({ id: item, title: item }) else if (item typeof item object typeof (item as Citation).id string typeof (item as Citation).title string) result.push(item as Citation) else return null } return result }这段代码只处理一个很小的兼容窗口。字段演进越复杂越应该使用明确的 schema 和契约测试而不是不断叠加临时分支。SSE 的重连与发布要一起测试流式连接可能在发布切流后仍保持也可能在中途断开后连接到另一版本服务。事件协议应有稳定的事件类型、请求 ID 与序号客户端应能忽略无关的扩展事件识别不兼容事件并结束当前流而不是让状态机停在“正在生成”。重连不等于重复执行。若流对应一个有成本的检索或生成任务服务端需要区分订阅已有任务、从某个序号重放以及重新创建任务。重放窗口、最大缓冲和授权校验要写清楚。灰度测试至少覆盖旧客户端连新服务、新客户端连旧服务、连接中途发布、断线重连和服务端主动取消。本地状态也需要版本和迁移策略回滚服务端并不会自动清掉浏览器里由新版本写入的数据。缓存数据建议带 schema version加载时先校验再迁移无法迁移时只丢弃相关缓存并保留用户仍需要的输入或草稿。不要因为一条历史消息格式坏了就清空全部对话。Pinia 等状态库的持久化范围也要克制。短生命周期的流式状态、服务端返回的完整原始对象、敏感数据都不适合无差别写入 localStorage。灰度期间应能按版本观察迁移失败率和渲染异常而不是只盯住接口成功率。验证结果要能触发明确动作灰度指标可以包括客户端错误、契约校验失败、SSE 完成率、重连后重复内容比例、缓存迁移失败和端到端完成时间。每项要有负责人与阈值对应的处置方式暂停扩大流量、回滚、关闭新事件还是引导客户端刷新。灰度的目标不是证明新版本没有任何问题而是在问题影响有限时把它看见、定位并撤回。把协议、长连接和本地状态作为同一条发布链路来验证才不会只在页面截图上看到一切正常。