当前位置: 首页 > news >正文

灰度发布专题---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:
--客户端
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配置如下:
    在这里插入图片描述
    上图代码如下:
#灰度系统负载均衡池
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脚本如下:

--客户端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配置如下:图片、静态页、样式、脚本,我们都进行灰度发布,如下配合

#静态资源 
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。
安装仓库管理工具包:

yum install yum-utils 

添加仓库地址:

yum-config-manager --add-repo 
https://openresty.org/package/centos/openresty.repo 

安装resty:

yum install openresty-resty 

安装opm:

yum install openresty-opm 

安装Jwt组件:

opm get SkyLothar/lua-resty-jwt 

此时 lua-resty-jwt安装好了,可以直接使用了。
在这里插入图片描述

ID识别

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

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用户校验令牌:

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配置如下:

#校验令牌 
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

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.VxhQcGihWyHuJeHhpUiq2FU7 aW2s_3ZJlY6h1kdlmJY 

校验令牌:http://192.168.211.142/check
在这里插入图片描述

ID切流实现

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

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修改配置如下:

#ID切流 
location =/1.html { 
#静态资源路径设置 
set $idpath ''; 
#lua脚本校验使用静态资源 
access_by_lua_file /usr/local/openresty/nginx/lua/id.lua; #静态资源root配置 
root $idpath; 
} 

相关文章:

  • C++空类的那点事儿
  • 虾皮在线定价工具:知虾轻松制定有竞争力的价格策略
  • 一张网页截图,AI帮你写前端代码,前端窃喜,终于不用干体力活了
  • Python技术操作1-高效办公:将文本、图片和表格信息批量写入Word文档
  • QList简单使用
  • Web安全-初识SQL注入(一)
  • 关于 Python 的最全面试题
  • 矩阵的初等变换
  • Maven——Maven发展历程
  • MySQL查看和修改时区
  • 西安安泰——ATA-1220E宽带放大器
  • 【单片机】单片机裸机实现多任务调度
  • 质量小议35 -- SQL注入
  • 第5章 固定通信网
  • 深入了解Java Period类,对时间段的精确控制
  • JavaScript-如何实现克隆(clone)函数
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • JavaScript DOM 10 - 滚动
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • js算法-归并排序(merge_sort)
  • nfs客户端进程变D,延伸linux的lock
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • PHP CLI应用的调试原理
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • redis学习笔记(三):列表、集合、有序集合
  • spring boot 整合mybatis 无法输出sql的问题
  • Spring声明式事务管理之一:五大属性分析
  • Zepto.js源码学习之二
  • 给github项目添加CI badge
  • 开发基于以太坊智能合约的DApp
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 前端之React实战:创建跨平台的项目架构
  • 区块链将重新定义世界
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 突破自己的技术思维
  • 微信小程序设置上一页数据
  • 我与Jetbrains的这些年
  • 原生 js 实现移动端 Touch 滑动反弹
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #define 用法
  • (0)Nginx 功能特性
  • (003)SlickEdit Unity的补全
  • (39)STM32——FLASH闪存
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (附源码)php投票系统 毕业设计 121500
  • (六)c52学习之旅-独立按键
  • (学习日记)2024.02.29:UCOSIII第二节
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .L0CK3D来袭:如何保护您的数据免受致命攻击