小程序图片上传失败排查:用 code=400 分布和 route_name 收敛到微信基础库灰度
2 月 10 日,好大夫部分小程序用户投诉上传图片失败。10 多人参与,排查三天。最终结论:微信在 2 月 9 日下午升级基础库,灰度 1% iOS 用户,2 月 11 日回滚;部分用户仍有异常,需要清理缓存。
排查过程:先切责任段,再看分布
按请求链路拆四段:用户侧、运营商传输节点、Kong 入口网关、后端图片服务。上传失败可能落在任一段。先做差异对比:同一用户切换网络仍失败;切到好大夫 APP 能上传成功。前端据此判断不是用户侧网络问题。Kong 日志里,部分用户重试多次都是 code=400。
怀疑链路传输:我们有多家网络节点运营商,切链路、直接回源后问题仍在。抓包并与运营商技术一起排查,未明确原因,运营商反馈仍是用户侧问题。
怀疑小程序版本:2 月 9 日有业务方向上线小程序,改的是 http2 相关,时间点对得上。紧急上线更新包,用户更新后问题依然存在。
怀疑 Kong 进程:2 月 11 日晚重启 Kong,担心进程启动太久、垃圾未回收。第二天问题未缓解。
对比最近几天 code=400 占比,2 月 10~11 日比之前多一倍;code=400 的 route_name 基本集中在小程序侧上传图片接口。范围收敛到小程序端后,联系微信社区、微信内部开发。2 月 13 日下午反馈:2 月 9 日下午微信升级基础库,灰度 1% iOS 用户,2 月 11 日回滚,部分用户还有异常需清理缓存。
判断顺序不是从组件开始猜,而是先用差异定位责任段:切网络失败、切 APP 成功,排除用户侧网络;切运营商链路和回源无效,排除传输节点;重启 Kong 无效,排除网关进程;2 月 9 日 http2 改动更新包后仍存在,排除该业务发布。再用 code 与 route_name 分布收敛:code=400、重试仍 400、route_name 集中传图接口,指向终端请求构造/基础库行为,而不是后端处理能力。最后才落到微信基础库灰度。
请求链路的四个责任段
- 用户侧:机器内存不足、小程序闪退;网络不稳定;上传过程中切到后台,重新唤起续传失败。
- 网络节点:请求到源站入口网关前先走运营商传输节点;传输节点对接多家运营商,传输不稳定或命中防火墙策略会失败。
- 入口网关 Kong:路由策略配置异常、Kong 节点异常、某个 upstream 节点异常都会失败。
- 后端图片服务:处理能力不足、负载高、进程夯住或其他异常会失败。
排查时先判段,再在段内看指标。
异常定位建模
异常定位要在参照系里做:把 SLI 波动可视化,比较不同 SLI 的波动振幅差异,推断可能原因;给异常建模并关联到可观测 SLI,透过 SLI 表象反查异常原因。提效的第一步是量化异常,让异常可观测;第二步是界面引导定位。
上传图片场景的 SLI
“两点一线,分两面,一面监控画像,一面异常定位”。梳理请求开始到结束,抓住两点连成一线。SLI 参考 Google VALET:Volume、Available、Latency、Error、Ticket。
SLO 两种设置:
- 固定阈值:按经验设,如 QPS 峰值不得大于 10k。
- 相对值:如
code=404环比增加 20%。
为了异常可观测,按不同维度细分 SLI。这次上传图片异常因微信灰度特定基础库,改造后收集终端信息:设备平台、设备型号、微信版本、微信基础库版本、小程序版本。
落地改造清单
用户侧:
- 每次小程序启动发探包请求,上报平台、版本、微信版本、微信基础库版本、小程序包名、小程序版本;不收集隐私。
- 通过 hash 生成版本信息指纹
hash_key;后续请求 URL 和 HTTP header 携带。 - 通过
hash_key关联 Kong 日志和版本信息,提炼终端不同维度 SLI。 - 小程序每次请求生成
trace_id,通过 header 透传。 - 网络不佳时先把 Error 日志暂存到 LocalStorage 队列,有网再上报;所有记录日志都带
trace_id。
网络节点:
- 新增运营商标识,方便对比不同运营商传输可用性。
- 收集运营商日志存储到 Clickhouse,让传输节点可观测。
入口网关:
- 按业务类型拆分
route_name,如上传、订单提交等。 route_name支持打标签:业务部门、所属页面;用于告警监控和识别风险,通知到具体部门。- 插件支持生成或透传
trace_id,打通 KongLog 和后端 TraceLog。
后端服务:
- 增加日志埋点,分析不同图片尺寸上传下载指标。
- 定义好不同 code 码。
数据与看板:
- SLI 存储到 Clickhouse,可视化基于 Grafana 写 SQL。
- 新增地理位置分析,将请求 IP 转经纬度。
改造中遇到的问题
- 控制 Error 信息大小。单条信息过大会导致 Flume 收集异常,出现重复收集或丢失日志。
- 采样上报,控制频次。异常可能连锁反应,瞬时大量日志,避免频繁上报消耗用户带宽。
- 降噪处理。腾讯周期性安全扫描会产生干扰异常,如 499,影响用户维度 SLI 准确性,需要识别干扰降噪。
- 提升分析性能,简化 SQL。很多分析要连表查询,数据量增大有性能问题;添加大量视图,重建不同维度索引表,将数据按分钟维度聚合成 SLI,避免查询原始日志的性能开销。
看板与判断路径
- 小程序分析首页:大盘投屏;上部分最近 15min 瞬时数据,大于经验阈值标红;下部分长期趋势,比对同比环比,面板支持下钻。列出最关心的 SLI,如 QPS/UV、慢路由请求数、异常请求数;根据时延和 ErrorCode 分布下钻。
- 长期趋势分析:最近 1 周/1 月/1 年宏观趋势,结合上线计划分析节点前后变化。
- Code 异常分析:首页观察异常 code 分布,下钻到具体 code 分析页。
- 是否需要人工介入?假定 SLO 为
code=400错误率<0.5%,p = total_400_request / (total_200_request + total_400_request)。如code=200访问量 10K,400 达到 500 则需人工介入。 - 同比环比是否有差异?分析当日请求判断是否突发,分析一周判断是否周期性。
- 是否有路由差异性?大面积无异常报错还是特定路由异常。
- 异常特征是否有终端平台、微信版本、微信基础库版本、小程序版本差异性?
- 差异显著性判断有认知误区:iPhone 异常数比 oppo 大,很可能是 iPhone 总体访问基数大,此时看各自长期占比趋势。
- 是否需要人工介入?假定 SLO 为
- 慢路由风险分析:关注 Top10 慢路由,分析长期慢还是突发抓取慢,结合 APM 链路分析。
- 路由详情分析:code 分布差异(如 P99 时延增加可能是
code=304缓存命中过低);同比环比差异,首要怀疑线上变更;是否抓取造成,分析 UA(hash ua)与 ClientIP 占比;地域差异;运营商节点差异;后端节点差异。 - 抓取分析:判断 UA 和 ClientIP 访问占比,抓取特征为单个 UA 访问量突增、ClientIP 集中,结合 QPM 长期趋势判断。