1.背景
公司一个服务需要上k8s集群,服务上了后,就是灰度流量。一开始灰度的规则很简单,比如example.com?version=gray,当get请求参数version等于gray,就会把流量导到k8s集群。后面开发提出的灰度规则麻烦了起来,比如当get请求参数是a==b and c==d时灰度,虽然只是多了一个参数判断,在nginx中确实麻烦了起来
2.使用lua
2.1.请求参数是1个时
if ($http_origin ~ http://example.com) {
proxy_pass http://gray_addr;
}
if ($query_string ~* "app_relation_id=11") {
proxy_pass http://gray_addr;
}
- 当灰度条件是1个时,就是拿nginx的内置变量做匹配
2.2.当请求参数是2个时
set $count 0;
if ($http_origin ~ http://example.com) {
set $count 1;
}
if ($query_string ~* "app_relation_id=11") {
set $count 2;
}
if ($count == 2){
proxy_pass http://gray_addr;
}
- 因为nginx if不支持and操作,只能写多个if判断,然后判断变量的值决定是否灰度
- 如果只写几个无所谓,当灰度条件多了请求,只能说是噩梦了
2.3.引入lua
- 正是因为nginx本身的一些缺陷,所以决定用lua实现
- 参考资料:
2.3.1 nginx lua支持
-
nginx lua的支持,需要重新编译nginx,教程不发了,反正用了一个下午加晚上也没搞定,后来直接下了openresty,停掉原来nginx,启动openresty
-
实现灰度
location / {
set $proxy_ip "";
rewrite_by_lua_block {
local ngx = require "ngx"
-- ngx.header["Access-Control-Allow-Origin"] = "*"
-- ngx.header["Access-Control-Allow-Headers"] = "*"
-- ngx.header["Access-Control-Allow-Credentials"] = "true";
-- source_id=448113c18c81f101 pay_method=wxa_jsapi 灰度条件
local args, err = ngx.req.get_uri_args()
if args['source_id'] == "448113c18c81f101" and args['pay_method'] == "wxa_jsapi" then
ngx.var.proxy_ip = "gray_addr"
else
ngx.var.proxy_ip = "origin_addr"
end
proxy_pass http://$proxy_ip;
}
- -- ngx.headers是lua注释的写法
- 灰度的思路很简单:一个if else语句搞定,稍微学习下lua语法就可以实现比较复杂的需求
2.3.2 一些坑
- 当出现错误时,一定要查看error.log,一开始我就盯着浏览器的报错,然后去搜索答案,一直解决不了问题
- 上面注释中ngx.headers就是一开始就是浏览器报的跨域问题,然后我配置了还是报跨域问题,但是查看error.log日志发现是proxy_ip变量为空,所以一定要查看error.log日志!
- ngx.say(),之前在rewrite_by_lua_block中写了这个函数,proxy_ip变量没有正常赋值,删除后可以,原理不太清楚
- 开发没有daemon方式启动后端服务,回家后电脑息屏然后断了,我TM是说咋upstream connet faild