灰度配置
1、openresty配置

2、参照nginx_2B.conf
#user appdeploy;
worker_processes 2;
error_log logs/2B_error.log;
#error_log logs/2B_error.log notice;
#error_log logs/2B_error.log info;
pid logs/nginx_2B.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent $request_time "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$upstream_addr $upstream_status $upstream_response_time';
access_log logs/2B_access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
tcp_nopush on;
tcp_nodelay on;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml application/json;
gzip_vary on;
gzip_proxied any;
client_max_body_size 5M;
#lua_package_path "/usr/local/fezs_bas_gray/?.lua;/usr/local/fezs_boms_gray/?.lua;/usr/local/openresty/fezs_mall_gray?.lua;/usr/local/fezs_b_gray/?.lua;/usr/local/openresty/lualib/?.lua;;";
lua_package_path "/usr/local/openresty/fezs_mgroup_gray/?.lua;/usr/local/fezs_bas_gray/?.lua;/usr/local/fezs_boms_gray/?.lua;/usr/local/openresty/fezs_mall_gray?.lua;/usr/local/fezs_b_gray/?.lua;/usr/local/openresty/ratelimiter-shopapi/?.lua;/usr/local/openresty/lualib/?.lua;;";
lua_package_cpath "/usr/local/openresty/lualib/?.so;;";
lua_shared_dict runtime 10m;
lua_shared_dict limitcache 100m;
lua_shared_dict blacklistcache 10m;
lua_shared_dict limitconfigcache 5m;
# Upstream Conf
upstream static_web_bas{
ip_hash;
server 10.200.130.43:8088 ;
server 10.200.130.35:8088 ;
}
upstream static_web_boms{
ip_hash;
server 10.200.130.43:8089 ;
server 10.200.130.35:8089 ;
}
upstream static_web_bssp{
ip_hash;
server 10.200.130.43:8090 ;
server 10.200.130.35:8090 ;
}
upstream static_web_mall{
ip_hash;
server 10.200.130.43:8091 ;
server 10.200.130.35:8091 ;
#server 10.200.130.43:8191 ;
}
upstream static_web_bmall{
ip_hash;
server 10.200.130.43:8092 ;
server 10.200.130.35:8092 ;
}
upstream static_web_scm{
ip_hash;
server 10.200.130.43:8093 ;
}
upstream static_web_bas_gray{
server 10.200.130.43:8188 ;
}
upstream static_web_boms_gray{
server 10.200.130.43:8189 ;
}
upstream static_web_bssp_gray{
server 10.200.130.43:8190 ;
}
upstream static_web_mall_gray{
server 10.200.130.43:8191 ;
}
upstream static_web_bmall_gray{
server 10.200.130.43:8192 ;
}
upstream static_web_scm_gray{
server 10.200.130.43:8193 ;
}
upstream bas_api{
server 10.200.130.14:8038 ;
server 10.200.130.3:8038 ;
}
upstream boms_api{
server 10.200.130.14:8048 ;
server 10.200.130.3:8048 ;
}
upstream bssp_api{
server 10.200.130.14:8058 ;
server 10.200.130.3:8058 ;
}
upstream mall_api{
server 10.200.130.7:8078 ;
server 10.200.130.12:8078 ;
}
upstream bmall_api{
server 10.200.130.26:8098 ;
server 10.200.130.27:8098 ;
}
upstream scm_api{
server 10.200.130.39:8108 ;
server 10.200.130.113:8108 ;
}
upstream bmall_api_gray{
server 10.200.130.90:8098 ;
}
upstream bas_api_gray{
server 10.200.130.90:9038 ;
}
upstream boms_api_gray{
server 10.200.130.90:9048 ;
}
upstream bssp_api_gray{
server 10.200.130.90:9058 ;
}
upstream mall_api_gray{
server 10.200.130.126:9078 ;
}
# wxadmin_api
upstream wxadmin_api_1{
server 10.200.130.3:8018 ;
server 10.200.130.14:8018 ;
}
upstream wxadmin_api_gray{
server 10.200.130.31:8018 ;
}
# wxapp_api
upstream wxapp{
server 10.200.130.7:8008 weight=5;
server 10.200.130.12:8008 weight=5;
#server 10.200.130.73:8008 weight=5;
#server 10.200.130.8:8008 weight=5;
}
upstream wxapp_gray{
#server 10.200.130.8:8008 weight=5;
server 10.200.130.136:8008 weight=5;
}
# Server Conf
server {
listen 8028;
server_name bas.feng1.com;
set $redis_host '10.200.130.138';
set $redis_port '6379';
set $redis_password 'DK11rrMN';
set $redis_connect_timeout 0;
set $redis_dbid 0;
set $redis_pool_size 100;
set $redis_keepalive_timeout 5000;
location /api {
set $runtime 'runtime';
set $backend 'bas_api';
rewrite ^/api/(.*)$ /$1 break;
rewrite_by_lua_file /usr/local/fezs_bas_gray/bas-api.lua;
#proxy_pass http://bas_api;
proxy_pass http://$backend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
set $runtime 'runtime';
set $backend 'static_web_bas';
rewrite_by_lua_file /usr/local/fezs_bas_gray/bas-web.lua;
#proxy_pass http://static_web_bas;
proxy_pass http://$backend;
proxy_redirect off;
#proxy_redirect http://bas.feng1.com:8088(.*) https://bas.feng1.com$1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /wxadmin {
set $runtime 'runtime';
set $backend 'wxadmin_api_1';
rewrite ^/wxadmin/(.*)$ /$1 break;
rewrite_by_lua_file /usr/local/fezs_bas_gray/bas-adminapi.lua;
proxy_pass http://$backend;
#proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 8029;
server_name boms.feng1.com bssp.feng1.com mall.feng1.com bmall.feng1.com scm.feng1.com;
rewrite ^(.*)$ https://$host$1 permanent;
}
server {
listen 8028;
server_name boms.feng1.com;
set $redis_host '10.200.130.138';
set $redis_port '6379';
set $redis_password 'DK11rrMN';
set $redis_connect_timeout 0;
set $redis_dbid 0;
set $redis_pool_size 100;
set $redis_keepalive_timeout 5000;
location /api {
set $runtime 'runtime';
set $backend 'boms_api';
rewrite ^/api/(.*)$ /$1 break;
rewrite_by_lua_file /usr/local/fezs_boms_gray/boms-api.lua;
#proxy_pass http://boms_api;
proxy_pass http://$backend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
set $runtime 'runtime';
set $backend 'static_web_boms';
rewrite_by_lua_file /usr/local/fezs_boms_gray/boms-web.lua;
#proxy_pass http://static_web_boms;
proxy_pass http://$backend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /wxadmin {
rewrite ^/wxadmin/(.*)$ /$1 break;
proxy_pass http://wxadmin_api_1;
#proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 8028;
server_name bssp.feng1.com;
set $redis_host '10.200.130.138';
set $redis_port '6379';
set $redis_password 'DK11rrMN';
set $redis_connect_timeout 0;
set $redis_dbid 0;
set $redis_pool_size 100;
set $redis_keepalive_timeout 5000;
location /api {
set $runtime 'runtime';
set $backend 'bssp_api';
rewrite ^/api/(.*)$ /$1 break;
rewrite_by_lua_file /usr/local/fezs_b_gray/b-api.lua;
#proxy_pass http://bssp_api;
proxy_pass http://$backend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
set $runtime 'runtime';
set $backend 'static_web_bssp';
rewrite_by_lua_file /usr/local/fezs_b_gray/b-web.lua;
#proxy_pass http://static_web_bssp;
proxy_pass http://$backend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 8028;
server_name mall.feng1.com;
access_log logs/mall.feng1.com.log main;
#redis gray
set $redis_host '10.200.130.138';
set $redis_port '6379';
set $redis_password 'DK11rrMN';
set $redis_connect_timeout 0;
set $redis_dbid 0;
set $redis_pool_size 100;
set $redis_keepalive_timeout 5000;
location /api {
set $runtime 'runtime';
set $backend 'mall_api';
set $limitcache 'limitcache';
set $blacklistcache 'blacklistcache';
set $limitconfigcache 'limitconfigcache';
rewrite_by_lua_file /usr/local/openresty/fezs_mall_gray/mall-api.lua;
rewrite ^/api/(.*)$ /$1 break;
access_by_lua_file /usr/local/openresty/ratelimiter-shopapi/ratelimiter-dict.lua;
proxy_pass http://$backend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /wxapp {
set $runtime 'runtime';
set $backend 'wxapp';
rewrite ^/wxapp/(.*)$ /$1 break;
rewrite_by_lua_file /usr/local/openresty/fezs_mall_gray/mall-wxapp-api.lua;
#proxy_pass http://wxapp_gray;
proxy_pass http://$backend;
#proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
set $runtime 'runtime';
set $backend 'static_web_mall';
rewrite_by_lua_file /usr/local/openresty/fezs_mall_gray/mall-web.lua;
proxy_pass http://$backend;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# location / {
# echo "system maintenance" ;
# }
}
server {
listen 8028;
server_name bmall.feng1.com;
access_log logs/bmall.feng1.com.log main;
set $redis_host '10.200.130.138';
set $redis_port '6379';
set $redis_password 'DK11rrMN';
set $redis_connect_timeout 0;
set $redis_dbid 0;
set $redis_pool_size 100;
set $redis_keepalive_timeout 5000;
location /mapi {
set $runtime 'runtime';
set $backend 'bmall_api';
rewrite ^/mapi/(.*)$ /$1 break;
rewrite_by_lua_file /usr/local/openresty/fezs_mgroup_gray/mgroup-api.lua;
proxy_pass http://$backend;
# proxy_pass http://bmall_api;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /wxapp {
set $runtime 'runtime';
set $backend 'wxapp';
rewrite ^/wxapp/(.*)$ /$1 break;
rewrite_by_lua_file /usr/local/openresty/fezs_mgroup_gray/mgroup-wxapp-api.lua;
proxy_pass http://$backend;
#proxy_pass http://wxapp_gray;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
set $runtime 'runtime';
set $backend 'static_web_bmall';
rewrite_by_lua_file /usr/local/openresty/fezs_mgroup_gray/mgroup-web.lua;
proxy_pass http://$backend;
# proxy_pass http://static_web_bmall;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 8028;
server_name scm.feng1.com;
access_log logs/scm.feng1.com.log main;
location /api {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://scm_api;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
proxy_pass http://static_web_scm;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
3、企业购灰度例子
lua文件路径

server配置

upstream
api

wxapp

web_bmall

4、redis配置

企业购灰度环境 Redis灰度操作 // 打开灰度开关 hset gray:mgroup switch on // 关闭灰度开关 hset gray:mgroup switch off // 查看灰度开关 hgetall gray:mgroup // 添加灰度用户 sadd gray:mgroup:userid (用户ID) // 删除灰度用户 srem gray:mgroup:userid (用户ID) // 查看所有灰度用户 smembers gray:mgroup:userid // 添加灰度ip sadd gray:mgroup:ip (ip) // 删除灰度ip srem gray:mgroup:ip (ip) // 查看所有灰度ip smembers gray:mgroup:ip // 添加api灰度upstream hset gray:mgroup:upstream api (对应upstream) // 删除api灰度upstream hdel gray:mgroup:upstream api // 添加api灰度upstream hset gray:mgroup:upstream wxappapi(对应upstream) // 删除api灰度upstream hdel gray:mgroup:upstream wxappapi // 配置web灰度upstream hset gray:mgroup:upstream web (对应upstream) // 删除web灰度upstream hdel gray:mgroup:upstream web // 查看灰度upstream hgetall gray:mgroup:upstream
5、lua文件

mgroup-api.lua
local redisModile = require('utils.redis')
local systemConf = require('utils.init')
local cache = require('utils.cache')
local ipParser = require('utils.ipParser')
local redisConf = systemConf.redisConf
local upstream = nil
local red = redisModile:new(redisConf)
local gray_type = "gray:mgroup:"
local redis_config_key = gray_type.."config"
local redis_userid_key = gray_type.."userid"
local redis_ip_key = gray_type.."ip"
local redis_upstream_key = gray_type.."upstream"
local dict_refresh_key = gray_type.."refresh"
local dict_switch_key = gray_type.."switch"
local dict_userid_api_key = gray_type.."userid:api"
local dict_userid_wxappapi_key = gray_type.."userid:wxappapi"
local dict_userid_web_key = gray_type.."userid:web"
local dict_ip_api_key = gray_type.."ip:api"
local dict_ip_wxappapi_key = gray_type.."ip:wxappapi"
local dict_ip_web_key = gray_type.."ip:web"
-- get all cookies
function get_cookies()
local cookies = ngx.header["Set-Cookie"] or {}
if type(cookies) == "string" then
cookies = {cookies}
end
return cookies
end
-- add cookie
function add_cookie(cookie)
local cookies = get_cookies()
table.insert(cookies, cookie)
ngx.header['Set-Cookie'] = cookies
end
-- get userId
function get_userid()
local userId = nil
userId = ngx.req.get_headers()["Feng1-UserId"]
if userId then
ngx.log(ngx.INFO, "head : userId = "..userId)
add_cookie("userId="..userId.."; Path=/; Expires="..ngx.cookie_time(ngx.time() + 180))
else
userId = ngx.var.cookie_userId
if not userId then
ngx.log(ngx.INFO, "userId is nil")
else
ngx.log(ngx.INFO, "cookies : userId = "..userId)
end
end
return userId
end
-- connect redis
local connectdb = function(red, redisConf)
if not red then
red = redisModile:new(redisConf)
end
local ok, err = red:connectdb()
if not ok then
ngx.log(ngx.ERR, "Redis connect error!")
return false, err
end
return ok, red
end
-- set redis pool
local setKeepalive = function(red)
local ok, err = red:keepalivedb()
if not ok then
ngx.log(ngx.ERR, "Redis keepalive error!")
return
end
end
-- check nginx cache,refresh 1 min
local checkfunc = function()
local runtimeCache = cache:new(ngx.var.runtime)
local refreshFlag = runtimeCache:getRefreshFlag(dict_refresh_key)
if refreshFlag then
ngx.log(ngx.INFO, 'cache refreshFlag:'..refreshFlag)
return true,'ok'
else
ngx.log(ngx.INFO, 'refresh cache......')
end
local ok, db = connectdb(red, redisConf)
local database = db.redis
runtimeCache:setRefreshFlag(dict_refresh_key)
local switch = database:hget(gray_type,"switch");
runtimeCache:setSwitch(dict_switch_key,switch)
local apiUpstream = database:hget(redis_upstream_key,"api");
local webUpstream = database:hget(redis_upstream_key,"web");
local wxappapiUpstream = database:hget(redis_upstream_key,"wxappapi");
local useridValues = database:smembers(redis_userid_key)
for key, value in pairs(useridValues) do
runtimeCache:setUpstream(dict_userid_api_key..value,apiUpstream)
runtimeCache:setUpstream(dict_userid_web_key..value,webUpstream)
runtimeCache:setUpstream(dict_userid_wxappapi_key..value,wxappapiUpstream)
end
local ipValues = database:smembers(redis_ip_key)
for key, value in pairs(ipValues) do
runtimeCache:setUpstream(dict_ip_api_key..value,apiUpstream)
runtimeCache:setUpstream(dict_ip_web_key..value,webUpstream)
runtimeCache:setUpstream(dict_ip_wxappapi_key..value,wxappapiUpstream)
end
if red then setKeepalive(red) end
end
local ok,err = pcall(checkfunc)
-- gray policy
local policyfunc = function()
local ups = nil
local runtimeCache = cache:new(ngx.var.runtime)
local switch = runtimeCache:getSwitch(dict_switch_key)
if "off" == switch then
return true,nil
end
-- use userid policy
local userid = get_userid()
if userid then
ups = runtimeCache:getUpstream(dict_userid_api_key..userid)
end
if ups then
upstream = ups
return true,ups
end
-- use ip policy
local ip = ipParser.get()
ups = runtimeCache:getUpstream(dict_ip_api_key..ip)
if ups then
upstream = ups
return true,ups
end
return true,nil
end
local ok,ups = pcall(policyfunc)
if upstream then
ngx.log(ngx.INFO, 'backend = '..upstream)
ngx.var.backend = upstream
end
mgroup-web.lua
local redisModile = require('utils.redis')
local systemConf = require('utils.init')
local cache = require('utils.cache')
local ipParser = require('utils.ipParser')
local redisConf = systemConf.redisConf
local upstream = nil
local red = redisModile:new(redisConf)
local gray_type = "gray:mgroup:"
local redis_config_key = gray_type.."config"
local redis_userid_key = gray_type.."userid"
local redis_ip_key = gray_type.."ip"
local redis_upstream_key = gray_type.."upstream"
local dict_refresh_key = gray_type.."refresh"
local dict_switch_key = gray_type.."switch"
local dict_userid_api_key = gray_type.."userid:api"
local dict_userid_wxappapi_key = gray_type.."userid:wxappapi"
local dict_userid_web_key = gray_type.."userid:web"
local dict_ip_api_key = gray_type.."ip:api"
local dict_ip_wxappapi_key = gray_type.."ip:wxappapi"
local dict_ip_web_key = gray_type.."ip:web"
-- get all cookies
function get_cookies()
local cookies = ngx.header["Set-Cookie"] or {}
if type(cookies) == "string" then
cookies = {cookies}
end
return cookies
end
-- add cookie
function add_cookie(cookie)
local cookies = get_cookies()
table.insert(cookies, cookie)
ngx.header['Set-Cookie'] = cookies
end
-- get userId
...skipping...
if red then setKeepalive(red) end
end
local ok,err = pcall(checkfunc)
-- gray policy
local policyfunc = function()
local ups = nil
local runtimeCache = cache:new(ngx.var.runtime)
local switch = runtimeCache:getSwitch(dict_switch_key)
if "off" == switch then
return true,nil
end
-- use userid policy
local userid = get_userid()
if userid then
ups = runtimeCache:getUpstream(dict_userid_web_key..userid)
end
if ups then
upstream = ups
return true,ups
end
-- use ip policy
local ip = ipParser.get()
ups = runtimeCache:getUpstream(dict_ip_web_key..ip)
if ups then
upstream = ups
return true,ups
end
return true,nil
end
local ok,ups = pcall(policyfunc)
if upstream then
ngx.log(ngx.INFO, 'backend = '..upstream)
ngx.var.backend = upstream
end
mgroup-wxapp-api.lua
local redisModile = require('utils.redis')
local systemConf = require('utils.init')
local cache = require('utils.cache')
local ipParser = require('utils.ipParser')
local redisConf = systemConf.redisConf
local upstream = nil
local red = redisModile:new(redisConf)
local gray_type = "gray:mgroup:"
local redis_config_key = gray_type.."config"
local redis_userid_key = gray_type.."userid"
local redis_ip_key = gray_type.."ip"
local redis_upstream_key = gray_type.."upstream"
local dict_refresh_key = gray_type.."refresh"
local dict_switch_key = gray_type.."switch"
local dict_userid_api_key = gray_type.."userid:api"
local dict_userid_wxappapi_key = gray_type.."userid:wxappapi"
local dict_userid_web_key = gray_type.."userid:web"
local dict_ip_api_key = gray_type.."ip:api"
local dict_ip_wxappapi_key = gray_type.."ip:wxappapi"
local dict_ip_web_key = gray_type.."ip:web"
-- get all cookies
function get_cookies()
local cookies = ngx.header["Set-Cookie"] or {}
if type(cookies) == "string" then
cookies = {cookies}
end
return cookies
end
-- add cookie
function add_cookie(cookie)
local cookies = get_cookies()
table.insert(cookies, cookie)
ngx.header['Set-Cookie'] = cookies
end
-- get userId
...skipping...
if red then setKeepalive(red) end
end
local ok,err = pcall(checkfunc)
-- gray policy
local policyfunc = function()
local ups = nil
local runtimeCache = cache:new(ngx.var.runtime)
local switch = runtimeCache:getSwitch(dict_switch_key)
if "off" == switch then
return true,nil
end
-- use userid policy
local userid = get_userid()
if userid then
ups = runtimeCache:getUpstream(dict_userid_wxappapi_key..userid)
end
if ups then
upstream = ups
return true,ups
end
-- use ip policy
local ip = ipParser.get()
ups = runtimeCache:getUpstream(dict_ip_wxappapi_key..ip)
if ups then
upstream = ups
return true,ups
end
return true,nil
end
local ok,ups = pcall(policyfunc)
if upstream then
ngx.log(ngx.INFO, 'backend = '..upstream)
ngx.var.backend = upstream
end

cookie.lua
[appdeploy@NG-GW1 resty]$ cat cookie.lua
-- Copyright (C) 2013-2016 Jiale Zhi (calio), CloudFlare Inc.
-- See RFC6265 http://tools.ietf.org/search/rfc6265
-- require "luacov"
local type = type
local byte = string.byte
local sub = string.sub
local format = string.format
local log = ngx.log
local ERR = ngx.ERR
local WARN = ngx.WARN
local ngx_header = ngx.header
local EQUAL = byte("=")
local SEMICOLON = byte(";")
local SPACE = byte(" ")
local HTAB = byte("\t")
-- table.new(narr, nrec)
local ok, new_tab = pcall(require, "table.new")
if not ok then
new_tab = function () return {} end
end
local ok, clear_tab = pcall(require, "table.clear")
if not ok then
clear_tab = function(tab) for k, _ in pairs(tab) do tab[k] = nil end end
end
local _M = new_tab(0, 2)
_M._VERSION = '0.01'
local function get_cookie_table(text_cookie)
if type(text_cookie) ~= "string" then
log(ERR, format("expect text_cookie to be \"string\" but found %s",
type(text_cookie)))
return {}
end
local EXPECT_KEY = 1
local EXPECT_VALUE = 2
local EXPECT_SP = 3
local n = 0
local len = #text_cookie
for i=1, len do
if byte(text_cookie, i) == SEMICOLON then
n = n + 1
end
end
local cookie_table = new_tab(0, n + 1)
local state = EXPECT_SP
local i = 1
local j = 1
local key, value
while j <= len do
if state == EXPECT_KEY then
if byte(text_cookie, j) == EQUAL then
key = sub(text_cookie, i, j - 1)
state = EXPECT_VALUE
i = j + 1
end
elseif state == EXPECT_VALUE then
if byte(text_cookie, j) == SEMICOLON
or byte(text_cookie, j) == SPACE
or byte(text_cookie, j) == HTAB
then
value = sub(text_cookie, i, j - 1)
cookie_table[key] = value
key, value = nil, nil
state = EXPECT_SP
i = j + 1
end
elseif state == EXPECT_SP then
if byte(text_cookie, j) ~= SPACE
and byte(text_cookie, j) ~= HTAB
then
state = EXPECT_KEY
i = j
j = j - 1
end
end
j = j + 1
end
if key ~= nil and value == nil then
cookie_table[key] = sub(text_cookie, i)
end
return cookie_table
end
function _M.new(self)
local _cookie = ngx.var.http_cookie
--if not _cookie then
--return nil, "no cookie found in current request"
--end
return setmetatable({ _cookie = _cookie, set_cookie_table = new_tab(4, 0) },
{ __index = self })
end
function _M.get(self, key)
if not self._cookie then
return nil, "no cookie found in the current request"
end
if self.cookie_table == nil then
self.cookie_table = get_cookie_table(self._cookie)
end
return self.cookie_table[key]
end
function _M.get_all(self)
if not self._cookie then
return nil, "no cookie found in the current request"
end
if self.cookie_table == nil then
self.cookie_table = get_cookie_table(self._cookie)
end
return self.cookie_table
end
local function bake(cookie)
if not cookie.key or not cookie.value then
return nil, 'missing cookie field "key" or "value"'
end
if cookie["max-age"] then
cookie.max_age = cookie["max-age"]
end
if (cookie.samesite) then
local samesite = cookie.samesite
-- if we dont have a valid-looking attribute, ignore the attribute
if (samesite ~= "Strict" and samesite ~= "Lax") then
log(WARN, "SameSite value must be 'Strict' or 'Lax'")
cookie.samesite = nil
end
end
local str = cookie.key .. "=" .. cookie.value
.. (cookie.expires and "; Expires=" .. cookie.expires or "")
.. (cookie.max_age and "; Max-Age=" .. cookie.max_age or "")
.. (cookie.domain and "; Domain=" .. cookie.domain or "")
.. (cookie.path and "; Path=" .. cookie.path or "")
.. (cookie.secure and "; Secure" or "")
.. (cookie.httponly and "; HttpOnly" or "")
.. (cookie.samesite and "; SameSite=" .. cookie.samesite or "")
.. (cookie.extension and "; " .. cookie.extension or "")
return str
end
function _M.set(self, cookie)
local cookie_str, err = bake(cookie)
if not cookie_str then
return nil, err
end
local set_cookie = ngx_header['Set-Cookie']
local set_cookie_type = type(set_cookie)
local t = self.set_cookie_table
clear_tab(t)
if set_cookie_type == "string" then
-- only one cookie has been setted
if set_cookie ~= cookie_str then
t[1] = set_cookie
t[2] = cookie_str
ngx_header['Set-Cookie'] = t
end
elseif set_cookie_type == "table" then
-- more than one cookies has been setted
local size = #set_cookie
-- we can not set cookie like ngx.header['Set-Cookie'][3] = val
-- so create a new table, copy all the values, and then set it back
for i=1, size do
t[i] = ngx_header['Set-Cookie'][i]
if t[i] == cookie_str then
-- new cookie is duplicated
return true
end
end
t[size + 1] = cookie_str
ngx_header['Set-Cookie'] = t
else
-- no cookie has been setted
ngx_header['Set-Cookie'] = cookie_str
end
return true
end
return _M
redis.lua
[appdeploy@NG-GW1 resty]$ cat redis.lua
-- Copyright (C) Yichun Zhang (agentzh)
local sub = string.sub
local byte = string.byte
local tcp = ngx.socket.tcp
local null = ngx.null
local type = type
local pairs = pairs
local unpack = unpack
local setmetatable = setmetatable
local tonumber = tonumber
local tostring = tostring
local rawget = rawget
--local error = error
local ok, new_tab = pcall(require, "table.new")
if not ok or type(new_tab) ~= "function" then
new_tab = function (narr, nrec) return {} end
end
local _M = new_tab(0, 54)
_M._VERSION = '0.26'
local common_cmds = {
"get", "set", "mget", "mset",
"del", "incr", "decr", -- Strings
"llen", "lindex", "lpop", "lpush",
"lrange", "linsert", -- Lists
"hexists", "hget", "hset", "hmget",
--[[ "hmset", ]] "hdel", -- Hashes
"smembers", "sismember", "sadd", "srem",
"sdiff", "sinter", "sunion", -- Sets
"zrange", "zrangebyscore", "zrank", "zadd",
"zrem", "zincrby", -- Sorted Sets
"auth", "eval", "expire", "script",
"sort" -- Others
}
local sub_commands = {
"subscribe", "psubscribe"
}
local unsub_commands = {
"unsubscribe", "punsubscribe"
}
local mt = { __index = _M }
function _M.new(self)
local sock, err = tcp()
if not sock then
return nil, err
end
return setmetatable({ _sock = sock, _subscribed = false }, mt)
end
function _M.set_timeout(self, timeout)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
return sock:settimeout(timeout)
end
function _M.connect(self, ...)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
self._subscribed = false
return sock:connect(...)
end
function _M.set_keepalive(self, ...)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
if rawget(self, "_subscribed") then
return nil, "subscribed state"
end
return sock:setkeepalive(...)
end
function _M.get_reused_times(self)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
return sock:getreusedtimes()
end
local function close(self)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
return sock:close()
end
_M.close = close
local function _read_reply(self, sock)
local line, err = sock:receive()
if not line then
if err == "timeout" and not rawget(self, "_subscribed") then
sock:close()
end
return nil, err
end
local prefix = byte(line)
if prefix == 36 then -- char '$'
-- print("bulk reply")
local size = tonumber(sub(line, 2))
if size < 0 then
return null
end
local data, err = sock:receive(size)
if not data then
if err == "timeout" then
sock:close()
end
return nil, err
end
local dummy, err = sock:receive(2) -- ignore CRLF
if not dummy then
return nil, err
end
return data
elseif prefix == 43 then -- char '+'
-- print("status reply")
return sub(line, 2)
elseif prefix == 42 then -- char '*'
local n = tonumber(sub(line, 2))
-- print("multi-bulk reply: ", n)
if n < 0 then
return null
end
local vals = new_tab(n, 0)
local nvals = 0
for i = 1, n do
local res, err = _read_reply(self, sock)
if res then
nvals = nvals + 1
vals[nvals] = res
elseif res == nil then
return nil, err
else
-- be a valid redis error value
nvals = nvals + 1
vals[nvals] = {false, err}
end
end
return vals
elseif prefix == 58 then -- char ':'
-- print("integer reply")
return tonumber(sub(line, 2))
elseif prefix == 45 then -- char '-'
-- print("error reply: ", n)
return false, sub(line, 2)
else
-- when `line` is an empty string, `prefix` will be equal to nil.
return nil, "unknown prefix: \"" .. tostring(prefix) .. "\""
end
end
local function _gen_req(args)
local nargs = #args
local req = new_tab(nargs * 5 + 1, 0)
req[1] = "*" .. nargs .. "\r\n"
local nbits = 2
for i = 1, nargs do
local arg = args[i]
if type(arg) ~= "string" then
arg = tostring(arg)
end
req[nbits] = "$"
req[nbits + 1] = #arg
req[nbits + 2] = "\r\n"
req[nbits + 3] = arg
req[nbits + 4] = "\r\n"
nbits = nbits + 5
end
-- it is much faster to do string concatenation on the C land
-- in real world (large number of strings in the Lua VM)
return req
end
local function _do_cmd(self, ...)
local args = {...}
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
local req = _gen_req(args)
local reqs = rawget(self, "_reqs")
if reqs then
reqs[#reqs + 1] = req
return
end
-- print("request: ", table.concat(req))
local bytes, err = sock:send(req)
if not bytes then
return nil, err
end
return _read_reply(self, sock)
end
local function _check_subscribed(self, res)
if type(res) == "table"
and (res[1] == "unsubscribe" or res[1] == "punsubscribe")
and res[3] == 0
then
self._subscribed = false
end
end
function _M.read_reply(self)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
if not rawget(self, "_subscribed") then
return nil, "not subscribed"
end
local res, err = _read_reply(self, sock)
_check_subscribed(self, res)
return res, err
end
for i = 1, #common_cmds do
local cmd = common_cmds[i]
_M[cmd] =
function (self, ...)
return _do_cmd(self, cmd, ...)
end
end
for i = 1, #sub_commands do
local cmd = sub_commands[i]
_M[cmd] =
function (self, ...)
self._subscribed = true
return _do_cmd(self, cmd, ...)
end
end
for i = 1, #unsub_commands do
local cmd = unsub_commands[i]
_M[cmd] =
function (self, ...)
local res, err = _do_cmd(self, cmd, ...)
_check_subscribed(self, res)
return res, err
end
end
function _M.hmset(self, hashname, ...)
if select('#', ...) == 1 then
local t = select(1, ...)
local n = 0
for k, v in pairs(t) do
n = n + 2
end
local array = new_tab(n, 0)
local i = 0
for k, v in pairs(t) do
array[i + 1] = k
array[i + 2] = v
i = i + 2
end
-- print("key", hashname)
return _do_cmd(self, "hmset", hashname, unpack(array))
end
-- backwards compatibility
return _do_cmd(self, "hmset", hashname, ...)
end
function _M.init_pipeline(self, n)
self._reqs = new_tab(n or 4, 0)
end
function _M.cancel_pipeline(self)
self._reqs = nil
end
function _M.commit_pipeline(self)
local reqs = rawget(self, "_reqs")
if not reqs then
return nil, "no pipeline"
end
self._reqs = nil
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
local bytes, err = sock:send(reqs)
if not bytes then
return nil, err
end
local nvals = 0
local nreqs = #reqs
local vals = new_tab(nreqs, 0)
for i = 1, nreqs do
local res, err = _read_reply(self, sock)
if res then
nvals = nvals + 1
vals[nvals] = res
elseif res == nil then
if err == "timeout" then
close(self)
end
return nil, err
else
-- be a valid redis error value
nvals = nvals + 1
vals[nvals] = {false, err}
end
end
return vals
end
function _M.array_to_hash(self, t)
local n = #t
-- print("n = ", n)
local h = new_tab(0, n / 2)
for i = 1, n, 2 do
h[t[i]] = t[i + 1]
end
return h
end
-- this method is deperate since we already do lazy method generation.
function _M.add_commands(...)
local cmds = {...}
for i = 1, #cmds do
local cmd = cmds[i]
_M[cmd] =
function (self, ...)
return _do_cmd(self, cmd, ...)
end
end
end
setmetatable(_M, {__index = function(self, cmd)
local method =
function (self, ...)
return _do_cmd(self, cmd, ...)
end
-- cache the lazily generated method in our
-- module table
_M[cmd] = method
return method
end})
return _M

cache.lua
[appdeploy@NG-GW1 utils]$ cat cache.lua
local modulename = "fezsgrayCache"
local _M = {}
_M._VERSION = '0.0.1'
local shdict_expire = 60
local upstream_expire = 180
_M.new = function(self, sharedDict)
if not sharedDict then
ngx.log(ngx.ERR, 'cache name valid from nginx.conf')
end
self.cache = ngx.shared[sharedDict]
if not self.cache then
ngx.log(ngx.ERR, 'cache name [' .. sharedDict .. '] valid from nginx.conf')
end
return setmetatable(self, { __index = _M } )
end
local isNULL = function(v)
return not v or v == ngx.null
end
_M.getRefreshFlag = function(self, key)
local cache = self.cache
local value = cache:get(key)
if isNULL(value) then
return nil
end
return value
end
_M.setRefreshFlag = function(self, key)
local cache = self.cache
local expire = shdict_expire
if key then
cache:set(key, 'no', expire)
end
end
_M.getUpstream = function(self, info)
local cache = self.cache
local upstream = nil
local ups = cache:get(info)
if not isNULL(ups) then
upstream = ups
end
return upstream
end
_M.setUpstream = function(self, info, upstream)
local cache = self.cache
local expire = upstream_expire
if info then
cache:set(info, upstream, expire)
end
end
_M.getSwitch = function(self, key)
local cache = self.cache
local value = nil
local tmp = cache:get(key)
if not isNULL(tmp) then
value = tmp
end
return value
end
_M.setSwitch= function(self, key, value)
local cache = self.cache
local expire = shdict_expire
if key then
cache:set(key, value, expire)
end
end
return _M
init.lua
[appdeploy@NG-GW1 utils]$ cat init.lua
local modulename = "fezsgrayInit"
local _M = {}
_M._VERSION = '0.0.1'
_M.redisConf = {
["host"] = ngx.var.redis_host,
["port"] = ngx.var.redis_port,
["password"] = ngx.var.redis_password,
["poolsize"] = ngx.var.redis_pool_size,
["idletime"] = ngx.var.redis_keepalive_timeout ,
["timeout"] = ngx.var.redis_connect_timeout,
["dbid"] = ngx.var.redis_dbid,
}
return _M
ipParser.lua
[appdeploy@NG-GW1 utils]$ cat ipParser.lua
local _M = {
_VERSION = '0.01'
}
local ffi = require("ffi")
ffi.cdef[[
struct in_addr {
uint32_t s_addr;
};
int inet_aton(const char *cp, struct in_addr *inp);
uint32_t ntohl(uint32_t netlong);
char *inet_ntoa(struct in_addr in);
uint32_t htonl(uint32_t hostlong);
]]
local C = ffi.C
local ip2long = function(ip)
local inp = ffi.new("struct in_addr[1]")
if C.inet_aton(ip, inp) ~= 0 then
return tonumber(C.ntohl(inp[0].s_addr))
end
return nil
end
local long2ip = function(long)
if type(long) ~= "number" then
return nil
end
local addr = ffi.new("struct in_addr")
addr.s_addr = C.htonl(long)
return ffi.string(C.inet_ntoa(addr))
end
_M.get = function()
local ClientIP = ngx.req.get_headers()["X-Forwarded-For"]
if ClientIP then
local i,j = string.find(ClientIP, ',')
if i then
ClientIP = string.sub(ClientIP, 1, i - 1)
end
end
if ClientIP == nil then
ClientIP = ngx.req.get_headers()["X-Real-IP"]
end
if ClientIP == nil then
ClientIP = ngx.var.remote_addr
end
--if ClientIP then
-- ClientIP = ip2long(ClientIP)
--end
return ClientIP
end
return _M
redis.lua
[appdeploy@NG-GW1 utils]$ cat redis.lua
local modulename = "fezsgrayRedis"
local _M = {}
_M._VERSION = '0.0.1'
local redis = require('resty.redis')
_M.new = function(self, conf)
self.host = conf.host
self.port = conf.port
self.password = conf.password
self.timeout = conf.timeout
self.dbid = conf.dbid
self.poolsize = conf.poolsize
self.idletime = conf.idletime
local red = redis:new()
return setmetatable({redis = red}, { __index = _M } )
end
_M.connectdb = function(self)
local host = self.host
local port = self.port
local password = self.password
local dbid = self.dbid
local red = self.redis
if not dbid then
dbid = 0
end
local timeout = self.timeout
if not timeout then
timeout = 10000 -- 10s
end
red:set_timeout(timeout)
local ok, err
if host and port then
ok, err = red:connect(host, port)
if not ok then
return false, err
end
local count
count, err = red:get_reused_times()
if 0 == count then
ok, err = red:auth(password)
if not ok then
return false, err
end
elseif err then
return false, err
end
if ok then
return red:select(dbid)
end
end
return ok, err
end
_M.keepalivedb = function(self)
local pool_max_idle_time = self.idletime --毫秒
local pool_size = self.poolsize --连接池大小
if not pool_size then pool_size = 1000 end
if not pool_max_idle_time then pool_max_idle_time = 90000 end
return self.redis:set_keepalive(pool_max_idle_time, pool_size)
end
return _M

浙公网安备 33010602011771号