请求在经过一层代理之后继续往前转发,头部的字段会跟着一起走。代理IP每转一层,头部就多留一份痕迹。转发层如果又补了一份,目标端就会收到同样的字段出现两次。多数情况下这不会立刻报错,问题会以另一种方式露出来:服务端读到的是后面那个值,处理逻辑和你以为的不一样。
哪些字段容易被重复添加
最常见的重复来自标识类字段。代理IP转发层为了让后端知道请求经过了哪一跳,会追加自己的标识;而客户端本来就已经带了一个。两个值都在的时候,按规范应该保留全部并以逗号连接,但不少实现只取其中一个。重复字段的麻烦不在语法,而在接收端选哪个值。不同服务端选择不一样,行为就不可预期了。
| 字段类别 | 为什么容易重复 | 规范建议 | 实操做法 |
|---|---|---|---|
| 来源标识 | 客户端与转发层各加一次 | 保留全部并连接 | 转发前先检查是否已存在 |
| 连接管理 | 多跳各自声明一次 | 以最后一跳为准 | 统一由最外层设置 |
| 转发地址 | 每跳追加自己的地址 | 按顺序全部保留 | 链路固定后转成静态配置 |
| 请求标识 | 重试时会重新生成 | 同一次请求保持一致 | 重试前保留原值不覆盖 |
同一个字段出现两次,读哪个由对方决定。
还有一类重复是自己造成的。同一份配置在多个地方各写了一遍,客户端加一次、代理IP转发层再加一次,多级链路叠上去就是三四份。这种重复与规范无关,纯粹是配置没对齐。排查时先看链路有几跳,再逐跳确认谁在加字段,比对着抓包结果猜要快。
排查顺序怎么排
- 数清链路一共经过几跳
- 逐跳确认谁在追加字段
- 对比客户端原始请求与服务端收到的内容
- 改完之后重新抓一次确认只剩一份
处理这类问题有个基本思路:能不加就不加,加之前先看有没有。转发层补字段之前,检查上游有没有已经带过;客户端配置里,避免重复声明同一个头。真的需要保留多个值的时候,明确约定用逗号连接还是分多行,两边对齐之后再上线,比上线之后再到日志里找规律划算。
另一种情况是字段被改写了。大小写不一致在很多实现里会被归一化处理,看起来像重复,其实是同一个字段的两种写法。这类问题不需要处理,但如果把大小写不同的字段当成两个不同的头来用,逻辑就会出错。
把链路的跳数和每跳的改写动作画出来,重复字段从哪来就一目了然。这件事做一次,后面排查同类问题能省很多时间。
