4. 追溯接口返回空数据的链路诊断
问题现象与诊断思路
追溯查询接口对某个已知存在的批次(例如 LOT-20240518-A)返回 {"code":0,"data":null},但该批次在赋码系统中确实已生成。空数据不等于数据不存在,它可能来自四个环节:请求参数被改写、网关路由到错误实例、缓存命中空值、数据库可见性过滤。诊断的核心是沿链路逐层"留痕",而不是直接查库。
逐层验证的关键动作
第一层:请求参数。在客户端与网关之间抓包,确认 lotCode 原样到达。常见问题是前端把批次号做了 trim 后仍带不可见字符,或网关对 query 做了大小写归一化,导致 lot-20240518-a 与库中大写值不匹配。
第二层:网关路由。查看网关访问日志中的 upstream_addr 与 X-Tenant-Id。若请求被路由到旧版本实例(如 trace-svc:v1),而该实例连接的是历史库,就会出现"数据存在但查不到"。
第三层:缓存。业务服务若对空结果做了短 TTL 缓存(防穿透),则首次查询失败后,后续请求会持续返回空值。用 redis-cli GET trace:lot:LOT-20240518-A 确认是否存在空值占位。
第四层:数据库可见性。直连库执行:
SELECT lot_code, tenant_id, status, deleted
FROM trace_lot
WHERE lot_code = 'LOT-20240518-A';
若行存在但 tenant_id 与请求头不一致,或 status='VOID'、deleted=1,则说明是可见性过滤导致空结果,而非数据丢失。
定位技巧:在业务服务入口打印
lotCode + tenantId + 路由实例IP 三元组日志,一次请求即可判断断点落在参数、路由还是过滤层。诊断记录表(可直接填写)
| 层级 | 验证对象 | 期望值 | 实际值 | 结论 |
|---|---|---|---|---|
| 参数 | 网关收到的 lotCode | LOT-20240518-A | 待填 | 一致/被改写 |
| 路由 | upstream_addr | trace-svc:v2 实例 | 待填 | 正确/错路由 |
| 缓存 | trace:lot:key | 无 key 或非空值 | 待填 | 空值缓存/正常 |
| 数据库 | trace_lot 行 | 存在且 tenant 匹配 | 待填 | 可见/被过滤 |
按表逐行填写后,第一个"实际值≠期望值"的层级即为断点位置。若四层均正常而接口仍返回空,则需检查业务服务的序列化逻辑是否把非空对象转成了 null。