接口层的资源大多有预算意识:连接数、超时、重试次数都会被认真设定。唯独请求头经常处于无人管理状态,直到某天调用量掉零、业务日志一片空白,最后在网关日志里发现全是 400。
四个膨胀源,都会自己长大:
一,追踪头累积。多跳调用每经过一层就追加一段追踪上下文,五跳叠出几 KB。二,中间层重复注入。网关、鉴权层、服务网格各加一遍自己的头,同名头出现三四次。三,凭证膨胀。权限明细塞进令牌随行,每次请求整份携带。四,业务参数进头。筛选条件、批量单号序列化后放自定义头——头是按「元数据」设计的,不是按「数据」设计的,这条没有上限。
三道闸的默认值互不同步: 反向代理常见默认 8KB,应用容器在 8–16KB 之间视实现而定,下游服务同样有限制。任何一道超限请求当场被拒,且不带业务信息。排查最耗时间的坑在这里:本层配置调到 16KB 依然报错,因为链路上还有其他节点各管各的 8KB。预算必须按整条链路的最小闸门算。
治理动作一:装秤。 入口中间件记录每请求的头总字节数与 Top5 大头,超预算记日志。闸门拒绝时不留痕,这行日志是排障的唯一线索来源:
@app.before_request def weigh_headers(): total = 0 items = [] for name, value in request.headers.items(): total += len(name.encode()) + len(value.encode()) + 4 items.append((len(name.encode()) + len(value.encode()) + 4, name)) items.sort(reverse=True) if total > 4 * 1024: logging.warning("HEADER_OVER|total=%d|top=%s", total, items[:5])
治理动作二:挪数据。 判定标准一条:头里放「关于请求的元信息」,不放「请求要处理的内容」。筛选条件、单号列表走请求体;追踪上下文单值传递;凭证只带标识与签名,权限明细走服务端查询。统一预算建议 4KB,给各层与增长留余量。
监控口径: 400 计数与头体积分位作为独立指标,网关层 400 突增自动告警。压测用例应包含大请求头场景——只压请求体不压请求头,三道闸的表现永远是未知的。
验收标准:
- 10KB 请求头打过去:网关拒收,且应用侧日志留下体积记录。
- 收敛一层注入:头总体积下降,追踪仍完整。
- 业务参数进请求体:头体积稳定在 1KB 内,与参数数量无关。
- 调小某层闸门:10 分钟内定位到是哪一道。
请求头预算的本质,是承认每一层中间件都会往请求里放东西,而没有任何一层会主动拿出来。