Nginx配置导致线上接口参数被修改

前几天在线上通过配置修改了请求中的某个参数的默认值,结果发现最终透传到我服接口的值和默认值对不上,经过排查,竟然发现是Nginx导致请求的参数被修改了!具体是啥原因,标题也说了。不妨和我一起追溯一下整件事情来龙去脉。

服务依赖关系

讲述事情之前,先讲解一下我们的服务依赖关系,服务间的依赖是和下面这张图一样的:

总控和线上服务间的依赖
总控和线上服务间的依赖

总控通过Nginx去请求数据包装服务的接口,数据包装服务又通过Nginx来请求我的服务。这里对上面的几个服务地址做一个假设。

  • 我的服务地址是:http://my-service-pod/v1/search?query=test
  • 对应的Nginx地址是:http://192.168.201.200:8081/search?query=test
  • 数据包装服务地址是:http://data-service-pod/api/search?query=test
  • 对应的Nginx地址是:http://192.168.201.200:8080/api/search?query=test

事情始末

由于我的某个接口对时效性要求比较高,因此做了一个处理,到了某个时间没有执行完成之后就中断执行直接返回结果。这个超时时间从请求方传过来的,参数名叫timeout,原来的值为1200。

某一天,由于我的有些外部依赖的耗时更长了,权衡利弊之后,最终选择调高超时时间,经过与请求方的沟通后,打算把总控的给的超时时间设置为2000,数据包装服务给的超时时间设置为1800,因此我接口收到的timeout参数的值应该是1800。

上线后结果非预期

我这边代码改好,然后测试环境自测并联调完成,一切正常。等到上线后,我这边发现收到的超时时间依旧是1200,好家伙,肯定是某个环节出问题了,开始逐层排查。一通排查下来,发现数据包装服务里面拿到的我上游Nginx的接口的结果和直接请求我上游Nginx的接口的结果不一致!

什么意思呢,举个简单的例子吧:

直接Get请求数据包装服务上游的Nginx地址,被简化和处理过的结果如下所示

## 请求方式
GET http://192.168.201.200:8080/api/search?query=test&timeout=2000
## 返回结果
{
    "status_code":0,
    "status_msg":"success",
    "data":{
        "query":"test",
        "timeout":1800
    },
    "debug":{
        "url":"http://192.168.201.200:8081/search?query=test&timeout=2000"
    }
}

从上面的Debug信息可以看出接口实际请求的地址是我上游的Nginx,且我的返回结果的timeout是1800而不是参数中的2000。但是直接使用Get请问我上游Nginx的地址,结果却是2000!

## 请求方式
GET http://192.168.201.200:8081/search?query=test&timeout=2000
## 返回结果
{
    "status_code":0,
    "status_msg":"success",
    "data":{
        "query":"test",
        "timeout":2000
    }
}

怀疑是数据包装服务问题

结果出来后,我就让数据包装服务的开发去查原因了,那哥们也是新接手的项目,对代码不是特别熟悉。理了一下逻辑之后,发现试环境无法复现,然后我去看了一下他线上和测试的版本,发现不一样。于是又和他沟通,内网使用一样的代码联调后,还是发现无法复现,匪夷所思啊。

然后那哥们去问了一下之前的开发人员,之前的开发说他们内部请求都是用的Post请求,看看是不是这个原因,一查,发现使用Post请求请求我的Nginx地址,并且将所有参数写在请求体里面结果果然和Get请求不一样!

## 请求方式
Post http://192.168.201.200:8081/search
{
    "query":"test",
    "timeout":2000
}

## 返回结果
{
    "status_code":0,
    "status_msg":"success",
    "data":{
        "query":"test",
        "timeout":1800
    }
}

但是直接Post请求我的真实地址,结果是正确的啊

## 请求方式
Post http://my-service-pod/v1/search
{
    "query":"test",
    "timeout":2000
}

## 返回结果
{
    "status_code":0,
    "status_msg":"success",
    "data":{
        "query":"test",
        "timeout":2000
    }
}

于是觉得肯定是Nginx出了问题,遂去找运维确认

怀疑是Nginx的问题

向运维拿到Nginx的配置之后,我大腿都拍断了,果然是Nginx搞的鬼,当时线上Nginx的配置如下:

location /search {
    rewrite_by_lua '
        ngx.req.read_body()
        if ngx.var.request_method == "POST" then
        local body = ngx.req.get_post_args();
        body.timeout = 1200
        ngx.req.set_body_data(ngx.encode_args(body))
        end;';
    set $proxy_upstream_name "default-my-prod-8080";
    proxy_pass http://hot_upstream_balancer/v1/search;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;

里面有一段Lua脚本,会将Post请求请求体中的timeout参数的值写死成1200!

于是尝试删除Lua代码片段后,更新Nginx配置

location /search {
    set $proxy_upstream_name "default-my-prod-8080";
    proxy_pass http://hot_upstream_balancer/v1/search;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;

重新请求后,发现结果正常了

事后整理

突然被Nginx坑了一下,还只是Post请求会这样。知道真相的我眼泪掉下来。

事后问了一下运维这玩意儿谁写的,说是历史原因接口有问题,使用Nginx暂时解决的,然后后面这个配置应该是大家都忘记了,所以导致了今天这个情况。

原创文章,创作不易,版权所有,抄袭必究

作者:幽叶草。如若转载,需要先经过作者同意,并附上原文链接 https://blog.uusite.com/develop/trouble-shooting/355.html

(0)
幽叶草的头像幽叶草
上一篇 2023年3月18日 上午11:44
下一篇 2023年3月29日 上午1:57

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注