问题背景
突然被抓来协助大数据的上报网关(OpenResty)
client -> OpenResty -> Kafka -> ClickHouse
这里的 OpenResty 负责数据的兼容, 过滤, 路由
因为需要经常的修改 OpenResty 的逻辑配合数据分析这边的需求
导致改动容易出现问题, 需要搞个测试环境.
通过测试环境的验证后, 在更新到正式环境
实施方案是使用 nginx 的 mirror 模块将请求镜像到测试站点.
同样的代码和配置, 通过环境变量来区分生产和测试环境
大概是这样的.
1 | (不返回client) |
那么问题来了
在实施中, 请求主站点时, 镜像站点也能收到请求
但一直显示status_code 400
, 从表现上来看像是 POST 的数据丢失了.
在 nginx 的 log_format 把$request_body
参数加上, 发现确实 POST 数据没有.
1 | 172.19.0.1 - [08/May/2020:06:35:09] "POST /user_login HTTP/1.0" 400 419 "-" |
思路验证
nginx 的配置问题?
难道是的配置有问题?
1 | ... |
主站点上日志的 POST 数据是没问题的, 所以很容易怀疑是 mirror 配置的问题
查看 nginx 的官网发现mirror_request_body
是用于控制镜像请求时是否附带 body 数据
1 | Syntax: mirror_request_body on | off; |
但这个参数默认是打开的, 所以不是这个问题.
OpenResty 的版本问题?
因为使用的 docker 来搭建的开发环境
并且长时间没有更新, 所以怀疑是不是版本兼容问题.
使用docker pull OpenResty/OpenResty
更新后发现…
也不是这个问题
业务配置的问题?
现在无法确定是主站点上的配置问题, 还是镜像站点上配置的问题.
所以使用 nginx 镜像配置了个干净的环境来进行测试.
1 | ... |
结果还是一样, 那么镜像站点的配置问题排除.
同样的使用 nginx 配置一个干净的主站点环境, 测试…
结果还是一样…
抓包确认
当时就纳闷了, 既然请求通过 mirror 模块发起请求都会出现问题.
那就确定了一下, 到底发出来的请求数据有没有问题.
先将 mirror 的地址改成本机(本地开发环境), 然后开启Wireshark
抓包
这么看来 mirror 模块的请求的 POST 数据是没问题的.
问题定位
现在我们知道了, 请求的数据是没问题的
但是通过 mirror 模块请求的 status_code 有问题
那就直接请求测试站点看看…
结果真相来了.
1 | <html> |
镜像站点的配置和主站点是一致的, 都是基于 ssl 的.
而主站点里的 mirror 模块使用的是proxy_pass http://127.0.0.1:8080$request_uri;
至此问题定位完毕, 修复起来也就很简单了.
复盘总结
细节问题
配置文件是直接复制的, 所以没有注意到细节.
对 http status_code 理解不深刻
之前工作中一直碰到的 400 都是缺少参数导致服务器处理不了
其实真正的意思是说 client 的请求错误, 不仅仅是参数, 经验主义啊.
1 | 6.5.1. 400 Bad Request |
从设计上来看
为什么设计上不将 http 请求 https 的错误作为一个独立的 status_code
猜测可能是因为将错误信息输出在了 respone text 里
所以就没有必要将单独作为一个 status_code, 毕竟这种情况也不常见.