nginx+lua+redis构建灰度服务

原创
2017/04/20 21:01
阅读数 1.9K

本系统采用nginx+lua+redis来实现灰度系统的动态路由控制。

1.采集灰度用户放入redis中

2.根据用户的cookie值反解析用户信息和之前存储的目标灰度用户进行对比。如果存在则请求灰度服务,否则请求正常服务。

nginx配置信息:

http {
    include       mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  logs/access.log  main;
    lua_package_path '/webapp/openresty/nginx/conf/?.lua;;';
    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

	
	 upstream client1 {
	 server  127.0.0.1:8081 weight=1;
    }
	 upstream client2{
	 server  127.0.0.1:8082 weight=1;
    }
	
    server {
        listen       8080;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }
		
		#前端请求到这里,解析并执行lua脚本
	  location /hnmccClient {
	    default_type text/plain; 
            content_by_lua_file /webapp/nginx/conf/waf/test.lua; 
            root   /;

        }
			
			
	 location @client1{
	   proxy_next_upstream    error timeout;
		proxy_redirect          off;
		proxy_set_header        Host $host;
		#proxy_set_header        X-Real-IP $remote_addr;
		proxy_set_header        X-Real-IP $http_x_forwarded_for;
		proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
		client_max_body_size    100m;
		client_body_buffer_size 256k;
		proxy_connect_timeout  180;
		proxy_send_timeout      180;
		proxy_read_timeout      180;
		proxy_buffer_size      8k;
		proxy_buffers          8 64k;
		proxy_busy_buffers_size 128k;
		proxy_temp_file_write_size 128k;
           proxy_pass http://client1;

       }

       location client2{
	        proxy_next_upstream    error timeout;
			proxy_redirect          off;
			proxy_set_header        Host $host;
			#proxy_set_header        X-Real-IP $remote_addr;
			proxy_set_header        X-Real-IP $http_x_forwarded_for;
			proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
			client_max_body_size    100m;
			client_body_buffer_size 256k;
			proxy_connect_timeout  180;
			proxy_send_timeout      180;
			proxy_read_timeout      180;
			proxy_buffer_size      8k;
			proxy_buffers          8 64k;
			proxy_busy_buffers_size 128k;
			proxy_temp_file_write_size 128k;
           proxy_pass http://client2;
       }

具体的lua脚本如下:

local userCookie = ngx.var.cookie_hncmjsSSOCookie
if(userCookie==nil or userCookie=="") then
  ngx.exec("@client1")
  return
end
local resultCookie = (string.gsub(userCookie,"@hn.ac.10086.cn",""))
if(resultCookie==nil or resultCookie=="") then
 ngx.exec("@client1")
 return
end
--引入nginx-redis模块
local redis = require "resty.redis"
--初始化redis客户端1
local red = redis:new()
--设置超时时间300ms
red:set_timeout(300) 
--建立连接
local ok, err = red:connect("127.0.0.1", 6380)
--如果建立连接失败,则请求正常服务
if not ok then
	ngx.exec("@client1")
	return
end
--通过cookie获取用户信息
local cookie = (string.gsub(resultCookie,"\"",""))
local userInfo = red:get(cookie)
local foo = require "foo"
local userInfoArr = foo.split(userInfo,"|")
--解析用户信息里面的手机号
local reqMobile = userInfoArr[10]
--如果手机号为空,则请求正常服务
if(reqMobile==nil or reqMobile=="") then
	ngx.exec("@client1")
	return
end
--初始化redis客户端2
local red2 = redis:new()
--设置超时时间300ms
red2:set_timeout(300) 
--建立连接
local ok2, err2 = red2:connect("127.0.0.1", 6380)
--如果建立连接失败,则请求正常服务
if not ok2 then
	ngx.exec("@client1")
	return
 end
--判断当前手机号是否在灰度目标群体中,如果存在,则请求灰度服务,否则请求正常服务
local flag = red2:sismember("AB_TEST",reqMobile)
if(flag == 1) then
	ngx.exec("@client2")
	return
end
ngx.exec("@client1")

上面用到了一个字符串拆分函数:

local _M = {}
function _M.split(s, delim)
    if type(delim) ~= "string" or string.len(delim) <= 0 then
        return
    end

    local start = 1
    local t = {}
    while true do
    local pos = string.find (s, delim, start, true) -- plain find
        if not pos then
          break
        end

        table.insert (t, string.sub (s, start, pos - 1))
        start = pos + string.len (delim)
    end
    table.insert (t, string.sub (s, start))

    return t
end
return _M

 

展开阅读全文
打赏
0
11 收藏
分享
加载中
更多评论
打赏
0 评论
11 收藏
0
分享
返回顶部
顶部