1. 问题背景与现象分析
最近在生产环境遇到一个典型的Nginx代理配置问题,导致所有经过新部署Nginx的请求都返回400错误。这个案例非常值得分享,因为它涉及HTTP协议规范、Nginx配置细节和SpringCloudGateway的交互问题。
我们的系统架构是这样的:
code复制客户端请求 -> 网关域名(wmg.test.com) -> Nginx集群 -> F5负载均衡 -> SpringCloudGateway -> 业务系统
运维团队新增了两台Nginx服务器替换旧机器后,立即出现以下现象:
- OPTIONS预检请求正常返回204
- 其他所有GET/POST请求都返回400 Bad Request
- 切回旧Nginx后问题立即消失
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 初步排查与错误定位
2.1 日志分析过程
首先检查了各组件日志:
- 网关日志:没有记录任何错误,说明请求在到达业务逻辑前就被拒绝
- Nginx访问日志:明确显示OPTIONS请求正常,其他请求返回400
- 网络流量回溯:确认400响应确实来自网关,而非后端业务系统
2.2 配置对比发现
对比新旧Nginx配置后,发现主要差异在于:
- 新配置使用了upstream模块定义后端服务
- 显式设置了HTTP/1.1协议和keepalive长连接
nginx复制upstream http_gateways{
server fp.wmg.test:8090;
keepalive 30;
}
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
# 其他配置...
proxy_pass http://http_gateways;
}
3. 问题复现与根因分析
3.1 测试环境复现
在测试环境搭建相同架构后,我们能够稳定复现该问题。关键发现:
- 当移除以下两行配置时,问题消失:
nginx复制proxy_http_version 1.1; proxy_set_header Connection ""; - 但网关实际是支持长连接的(通过wget测试验证)
3.2 数据包分析
通过tcpdump抓包分析,发现关键问题:
- 请求头中的Host值被设置为
http_gateways - 这个值来自upstream模块名称
- 包含下划线
_的Host值违反了HTTP/1.1规范
3.3 协议规范解读
根据RFC 2616:
- HTTP/1.1强制要求Host头
- Host值只能包含字母数字、点和连字符
- 下划线是非法的(尽管某些实现可能容忍)
SpringCloudGateway作为严格
