nginx lua灰度和一些坑

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

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