灰度发布专题---3、Nginx+Lua灰度发布

上一章已经讲解了配置文件灰度发布、应用版本灰度发布、API网关灰度发布实现,但如果用户这时候在代理层如何做灰度发布呢?

代理层灰度发布分析

用户无论访问应用服务还是静态页,都要经过Nginx代理层,我们可以在Nginx这里做灰度发布,这里的灰度发布可以分为静态页灰度发布和应用动态发布,

如上图:动态服务灰度发布IP/ID切流:

  • zhangsan、wangwu使用A应用
  • zhaoliu使用B应用
  • 192.168.211.1/192.168.211.2 IP的用户使用A应用
  • 192.168.211.3 IP的用户使用B应用

静态资源灰度发布IP/ID切流:

  • zhangsan、wangwu访问静态页,使用/usr/bj目录下的静态页
  • zhaoliu访问静态页,使用/usr/tj目录下的静态页
  • 192.168.211.1/192.168.211.2 IP的用户使用/usr/sz目录下的静态页

IP分流灰度发布

我们为了测试系统,通常把公司内部IP设置为测试IP,也就是使用灰度系统的IP,此时内部员工测试直接访问服务器即可,但是访问服务器又分为静态资源访问和动态服务访问,都有不同的实现策略。在代理层实现灰度发布,可以采用Nginx+Lua实现。

动态服务灰度发布

IP切流动态服务灰度发布方式的实现要借助Nginx+Lua和Redis了,我们可以先把公司内部的IP全部存储在Redis缓存中,当用户访问系统的时候,先通过Lua脚本根据IP查询Redis缓存,如果Redis缓存数据存在就表明使用灰度系统,如果没有缓存则使用稳定版系统。

IP切流步骤如上图:

  1. IP校验
    在服务器上创建lua脚本文件/usr/local/openresty/nginx/lua/loadip.lua:
bash 复制代码
--客户端
IPlocal headers=ngx.req.get_headers()
local ip=headers["X-REAL-IP"] or headers["X_FORWARDED_FOR"] or 
ngx.var.remote_addr or "0.0.0.0"
--local ip = "192.168.211.1"

--引入redis依赖
local redis = require("resty.redis");
local red = redis:new()
red:set_timeout(2000)
red:connect("192.168.211.142", 6379)
--执行查询
local grayresult=red:get(ip);
red:close()

if grayresult==nil or grayresult==nil or grayresult==ngx.null then 
--没有数据则查询主服务 
ngx.var.upstream = "sys"
else 
--如果有数据,则查询灰度服务 
ngx.var.upstream = "gray"
end
  1. Nginx控制配置:
    修改nginx.conf配置如下:

    上图代码如下:
bash 复制代码
#灰度系统负载均衡池
upstream gray { 
server 192.168.211.1:18082;
}
#稳定系统负载均衡池
upstream sys { 
server 192.168.1.5:18081;
}
server {    
listen       80;    
server_name localhost;    
#charset koi8-r;    
#access_log logs/host.access.log main;
#所有动态请求    
location / {        
#设置负载均衡池        
set $upstream '';        
#查找负载均衡池        
access_by_lua_file /usr/local/openresty/nginx/lua/loadip.lua;        
#反向代理        
proxy_pass http://$upstream;   
}
}
  1. 效果测试

    在Redis中添加IP 192.168.211.1,访问时会走灰度发布系统,把IP删除会走稳定系统。

静态资源灰度发布

我们把稳定静态资源和灰度静态页资源分别放在了 /usr/local/openresty/nginx/static1/ 和 /usr/local/openresty/nginx/static2/目录下,我们要求公司员工IP访问灰度发布的静态页, 非公司员工IP访问稳定版本页面,这里又需要用到指定IP查询了。

创建 home.lua脚本如下:

bash 复制代码
--客户端IP 
local headers=ngx.req.get_headers() 
local ip=headers["X-REAL-IP"] or headers["X_FORWARDED_FOR"] or ngx.var.remote_addr or "0.0.0.0" 
--local ip = "192.168.211.1" 
--引入redis依赖 
local redis = require("resty.redis"); 
local red = redis:new() 
red:set_timeout(2000) 
red:connect("192.168.211.142", 6379) 
--执行查询 
local grayresult=red:get(ip); 
red:close() 
if grayresult==nil or grayresult==nil or grayresult==ngx.null then --没有数据则查询主服务 
ngx.var.homepath = "/usr/local/openresty/nginx/static1/" 
else 
--如果有数据,则查询灰度服务 
ngx.var.homepath = "/usr/local/openresty/nginx/static2/" 
end

nginx.conf配置如下:图片、静态页、样式、脚本,我们都进行灰度发布,如下配合

bash 复制代码
#静态资源 
location ~* \.(jpg|png|html|css|js|woff|ttf|woff2) { 
#静态资源路径设置 
set $homepath ''; 
#lua脚本校验使用静态资源 
access_by_lua_file /usr/local/openresty/nginx/lua/home.lua; #静态资源root配置 
root $homepath; 
} 

ID切流灰度发布

现在的项目大多数已经是微服务项目,而微服务项目几乎都是前天传递JWT令牌到后台,要想实现ID切 流,我们需要在代理层识别用户身份(JWT令牌),我们需要引入 lua-resty-jwt模块,是用于 ngx_lua 和 LuaJIT 的 Lua 实现库,在该模块能实现Jwt令牌生成、Jwt令牌校验,依赖库的地址:http s://github.com/SkyLothar/lua-resty-jwt。

JWT令牌识别库安装

将下载好了该依赖库 lua-resty-jwt-master.zip,我们将该库文件上传到服务器上,并解压,当然,我 们也可以使用opm直接安装 lua-resty-jwt,配置 lua-resty-jwt之前,我们需要先安装resty和 opm。

安装仓库管理工具包:

bash 复制代码
yum install yum-utils 

添加仓库地址:

bash 复制代码
yum-config-manager --add-repo 
https://openresty.org/package/centos/openresty.repo 

安装resty:

bash 复制代码
yum install openresty-resty 

安装opm:

bash 复制代码
yum install openresty-opm 

安装Jwt组件:

bash 复制代码
opm get SkyLothar/lua-resty-jwt 

此时 lua-resty-jwt安装好了,可以直接使用了。

ID识别

我们先利用 lua-resty-jwt生成令牌,再解析令牌 创建 make.lua用于生成令牌:

bash 复制代码
ngx.header.content_type="application/json;charset=utf8" local cjson = require "cjson" 
local jwt = require "resty.jwt" 
--生成令牌 
--lua-resty-jwt为秘钥 
local jwt_token = jwt:sign( 
"lua-resty-jwt", 
{ 
header={typ="JWT", alg="HS256"}, 
payload={name="zhangsan"} 
} 
) 
ngx.say(jwt_token) 

创建 token.lua用户校验令牌:

bash 复制代码
local cjson = require "cjson" 
local jwt = require "resty.jwt" 
--获取请求头中的令牌数据 
local auth_header = ngx.var.http_Authorization 
local jwt_obj = jwt:verify("lua-resty-jwt", auth_header) ngx.say(cjson.encode(jwt_obj)) 

nginx.conf配置如下:

bash 复制代码
#校验令牌 
location /check { 
content_by_lua_file /usr/local/openresty/nginx/lua/token.lua; } 
#生成令牌 
location /token { 
content_by_lua_file /usr/local/openresty/nginx/lua/make.lua; } 

生成令牌:http://192.168.211.142/token

bash 复制代码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.VxhQcGihWyHuJeHhpUiq2FU7 aW2s_3ZJlY6h1kdlmJY 

校验令牌:http://192.168.211.142/check

ID切流实现

结合上面JWT令牌识别,可以编写一个ID切流的流程,我们这里假设是zhangsan用户就访问灰度版本, 其他用户访问稳定版本,创建id.lua如下代码:

bash 复制代码
local cjson = require "cjson" 
local jwt = require "resty.jwt" 
--获取请求头中的令牌数据 
local auth_header = ngx.var.http_Authorization 
local jwt_obj = jwt:verify("lua-resty-jwt", auth_header) --解析的用户名 
local username = jwt_obj["payload"]["name"] 
if username=="zhangsan" then 
--没有数据则查询主服务 
ngx.var.idpath = "/usr/local/openresty/nginx/static1/" 
else
--如果有数据,则查询灰度服务 
ngx.var.idpath = "/usr/local/openresty/nginx/static2/" 
end

nginx.conf修改配置如下:

bash 复制代码
#ID切流 
location =/1.html { 
#静态资源路径设置 
set $idpath ''; 
#lua脚本校验使用静态资源 
access_by_lua_file /usr/local/openresty/nginx/lua/id.lua; #静态资源root配置 
root $idpath; 
} 
相关推荐
嵌入式-老费4 小时前
Easyx图形库应用(和lua结合使用)
开发语言·lua
程序员大辉7 小时前
接口调试利器,Postman免安装,免登陆
测试工具·lua·postman
天庭鸡腿哥8 小时前
可能最后一个版本,作者不更新了!
eclipse·maven·lua·visual studio
fruge16 小时前
Ubuntu服务器已下载Nginx安装包的安装指南
服务器·nginx·ubuntu
siriuuus17 小时前
Linux Tomcat 简单使用及 Nginx 反向代理
linux·nginx·tomcat
li37149089020 小时前
nginx报400bad request 请求头过大异常处理
java·运维·nginx
Crazy________1 天前
34部署LNMP架构详细解析
linux·运维·服务器·nginx
FFZero11 天前
【C++/Lua联合开发】 (三) C++调用Lua
c++·junit·lua
木易 士心2 天前
Nginx 基本使用和高级用法详解
运维·javascript·nginx
疯狂吧小飞牛2 天前
Lua C API 中的 lua_rawseti 与 lua_rawgeti 介绍
c语言·开发语言·lua