题干与适用场景
设计一个影子流量系统,服务每秒接收 20,000 个请求。主请求必须保持现有 p99 延迟,影子版本可以滞后。系统需要按端点采样,保留足够证据重放差异,并保证镜像请求不会发送付款、邮件或其他外部副作用。
核心是应用层请求镜像,不是网络抓包。负载均衡器可以异步发送一份 fire-and-forget 副本到镜像后端,主响应仍是唯一权威结果。网络流量镜像有不同的目标和封装,不能替代理解端点语义的重放链路。
面试官考察点
面试官要的是安全的比较工具,而不是复制一套生产服务。强回答会保护主链路延迟、移除凭证、隔离写入、让采样可复现,并解释为什么逐字节比较通常不正确。
面试官会追问捕获队列满、影子服务变慢、响应含时间戳,以及主服务已经写入外部系统时怎么办。每个场景都要有明确策略。
回答前需要澄清的问题
- 请求是否只读?只读请求可以直接重放;写请求需要沙箱、桩或合成身份。
- 比较是精确还是语义比较?确定性 JSON 可精确比较;时间戳和随机 ID 应使用掩码或不变量。
- 捕获内容是否含个人资料?如果有,要在存储前脱敏、加密引用、定义保留期和访问审计。
- 目标是迁移正确性、延迟还是容量?目标不同,指标和采样策略也不同。
30 秒回答框架
“我会在授权之后、外部写入之前捕获请求,清理密钥和个人资料,再异步放入可复现的采样队列。主响应仍然直接返回。隔离的影子 worker 使用独立凭证、沙箱和有界速率重放。差异服务比较状态码、选定字段、不变量和延迟,忽略声明过的非确定性字段。队列溢出时丢弃镜像而不拖慢用户。发布前要有差异率、错误率、隐私和容量门槛,并确认没有不安全副作用。”
分步骤深入解答
1. 不触碰关键链路地捕获
把捕获钩子放在认证授权之后、不可逆外部调用之前。只复制影子需要的字段,移除 Authorization、Cookie、用户令牌和支付信息,换成短期影子凭证或固定测试身份。
发布 MirroredRequest,包含请求 ID、trace ID、端点、脱敏请求头、正文引用、捕获时间、目标版本和采样配置版本。入队必须有上限时间;缓冲或持久队列满时记录丢弃指标并返回主响应。
2. 让采样可复现
对稳定的请求 ID 或 trace ID 做哈希,与配置的采样率比较,保证重试和调查时结果稳定。再按端点和租户使用令牌桶限制镜像 RPS,采样比例和令牌预算取更小值。
每次捕获都保存采样配置版本,报告才能区分真实差异和采样规则变化。
3. 在隔离环境中重放
worker 从持久队列读取,用短超时请求影子版本。影子必须使用独立数据库或事务桩,付款和邮件供应商要替换成 stub,并关闭外呼回调。只读请求通常使用只读副本或脱敏快照更安全。
捕获队列采用至少一次投递没有问题,因为重放带请求 ID。worker 记录 SHADOW_ERROR、DROPPED 或 COMPLETED;影子超时不能无限重试,也不能阻塞主请求。
4. 按语义比较响应
先比较状态码。成功 JSON 去掉明确声明的非确定性字段,再比较选定路径或规范化后的 body hash。加入业务不变量,例如总额不能为负、返回用户必须属于请求租户。延迟单独比较,响应正确但太慢也不能发布。
保存两侧 hash、差异路径、主侧与影子延迟、部署版本和样本请求引用。报告中不要保存敏感正文。
5. 定义发布门槛
重放前先定义差异率、影子错误率、延迟回归、队列年龄和脱敏失败阈值。按端点、租户层级、地区和响应类别切分;总差异率为绿不能掩盖支付端点损坏。
使用滑动窗口和最小样本量。1% 差异阈值只是示例政策,不是通用规则。发布还要满足无不安全副作用、影子容量可承受,并审阅每个高严重度差异的样本。
6. 运行与恢复
影子过载时暂停重放,不必关闭捕获。按隐私政策过期样本,审计请求引用的访问。影子版本回滚后,报告仍要关联部署版本,避免不同版本混在一起分析。
测试队列丢失、重复捕获、过期配置、凭证泄漏、副作用尝试、非确定字段、影子超时和地区故障。成功标准是主服务仍满足 SLO,影子输出可操作、可复现的证据。
高质量示范回答
“我会在认证授权之后、外部写入之前加入应用层镜像钩子。它移除真实凭证和敏感字段,保存正文引用,并按 trace ID 可复现地采样。主链路不等待镜像,队列有压力时可以丢弃镜像工作。
“隔离 worker 使用独立身份、数据库和桩供应商重放到影子版本。每次重放都带请求 ID 和超时。比较服务检查状态码、选定 JSON 路径、业务不变量和延迟,只忽略声明过的非确定字段。报告保留 hash、差异路径、版本和脱敏样本。
“发布前设置端点级差异、错误、延迟、队列年龄和隐私门槛,要求足够样本并审阅严重差异。写请求必须进入沙箱,无法隔离的端点直接排除并说明覆盖缺口。最后验证队列溢出、重复、凭证清理、副作用和地区故障,同时证明主 SLO 未受影响。”
常见错误
- 错误表现 → 失败原因 → 修正方法: 重放生产凭证 → 影子调用可能泄漏或修改真实系统 → 清理密钥,使用隔离身份、数据库和供应商。
- 错误表现 → 失败原因 → 修正方法: 等影子响应后再返回 → 迁移验证增加用户延迟 → 异步入队,压力大时丢弃镜像。
- 错误表现 → 失败原因 → 修正方法: 只比较原始正文 → 时间戳和随机 ID 制造假差异 → 规范化并比较字段和不变量。
- 错误表现 → 失败原因 → 修正方法: 永久镜像全部请求 → 存储、隐私和容量无限增长 → 使用可复现采样、配额、保留期和审计。
- 错误表现 → 失败原因 → 修正方法: 只看全局差异率 → 小型关键端点可能在绿灯总指标中失败 → 按端点、租户、地区和严重度设门槛。
追问及应对
如果端点会写数据库怎么办?
把影子请求路由到一次性数据库或事务桩,用 fake 记录付款、邮件等外部调用意图。无法隔离的端点就排除,并明确覆盖缺口,不要假装结果安全。
如果捕获队列满了怎么办?
主请求选择 fail-open:丢掉镜像副本、增加带标签的指标,超过丢弃预算再告警。主链路背压会破坏安全属性。
如何处理个人可识别信息?
捕获时给字段分类,在持久化前脱敏或令牌化,加密正文引用,限制保留期并审计访问。敏感正文的 hash 仍可能具备识别性,不能自动视为安全。
网络流量镜像能替代应用层镜像吗?
不能。网络镜像复制流量到分析目标,应用层镜像理解端点语义、凭证、租户策略和响应比较。网络镜像适合检查网络,行为验证需要应用层路径。