关于 lua 中对 nginx 变量处理后 proxy_pass 出现问题的疑问

2021-11-25 14:56:18 +08:00
 laev
xdm 好,我是个前端,运维方面的菜鸡,请教大家一下

我用 openresty 搭建了个简陋版本的灰度切换方案,但是 lua 脚本运行之后好像出了点问题

-------------------------test.conf start-----------------------------
upstream production_server {
server 123.123.123.123:80;
}
upstream grayscale_server {
server 456.456.456.456:80;
}

server {
listen 80;
server_name localhost;
lua_code_cache off;
set $default_stream "production_server";
set $grayscale_stream "grayscale_server";
# 运行脚本读取策略
access_by_lua_file /usr/local/openresty/lua/main.lua;

location / {
default_type text/html;
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_redirect off;
proxy_pass $scheme://$default_stream;
proxy_next_upstream http_500 http_503 error;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/openresty/nginx/html;
}
}
-------------------------test.conf end-----------------------------

-------------------------main.lua start-----------------------------
local redisutils = require("redisutils")
local controller = require("controller")
local red = redisutils.redisClient()
local params = ngx.req.get_uri_args()
local userId = params.userId

if red then
local is_grayscale = controller.checkUserId(red, userId)
if is_grayscale then
ngx.var.default_stream = ngx.var.grayscale_stream
end
redisutils.closeRedis(red)
end
-------------------------main.lua end-----------------------------

我把$default_stream 直接替换为“production_server” 或 “grayscale_server” 都没有问题
但是 lua 运行后,大概是这一句 ngx.var.default_stream = ngx.var.grayscale_stream
index.html 中的 js 和 css 等使用相对路径(“/js/xxx.js”)的资源都似乎回源到了代理机器本身,从而最终找不到资源

如果哪位大佬有办法解决,希望不吝赐教一下,或者说有更好的方法也可以。

感谢!!!
1667 次点击
所在节点    NGINX
4 条回复
eason1874
2021-11-25 15:44:18 +08:00
静态文件链接不带 userId 参数吧,按你的代码,链接没有 userId 判断不了是否灰度

但是判断不了也应该回源 production_server 啊,怎么会是代理机器呢,你确定没搞错?
laev
2021-11-26 09:22:39 +08:00
@eason1874 确实是我搞错了,最终回源到的是 production_server 。我有点疑问的是当$default_stream 为 production_server 也就是默认值的时候,静态文件是可访问的,似乎 nginx 自动处理了$args ,同时 $default_stream 替换为 grayscale_server 也是可以访问的。我尝试在配置文件中写入
access_by_lua_block {
ngx.var.default_stream = ngx.var.grayscale_stream
}
这样也能成功读取到,目前似乎是在引用 lua 脚本运行赋值时没有获得 userId 从而导致资源被指向 production_server
eason1874
2021-11-26 14:11:09 +08:00
@laev 你的代码根据网址参数 userId 判断是否灰度,静态文件链接没有这个参数啊

比如你允许 userId 为 1 的灰度, 当请求 //localhost/?userId=1 时会匹配到灰度,但是网页里面的资源比如 /js/a.js 不会匹配到灰度,因为不是 /js/a.js?userId=1 ,缺少必要参数

解决办法就是换别的方式传参。比如用 Cookies ,但是 Cookies 动态判断的缺点很多,客户端禁用 Cookies 的时候不管用,要在 CDN 缓存静态资源时不管用,等等

所以不同版本的静态资源路径通常是写死的,部署自动在路径加上文件版本号,比如 /js/a-{filehash}.js ,新版本引用新的文件就不会读取到旧文件

前端服务在静态文件路径同时反代生产和灰度环境,proxy_next_upstream http_404 ,生产 404 就读灰度,然后把结果缓存并返回
laev
2021-11-29 10:28:21 +08:00
@eason1874 明白了,十分感谢!我一直以来走进死胡同了。。感觉自己有点蠢[笑哭]

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/817916

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX