文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

nginx+lua+redis 灰度发布实现方案

2024-10-10 18:02

关注

背景: 公司要把现有的某传统项目进行微服务化,拆分后要分批次预发布,实现某部分使用户使用微服务模块,其他用户使用传统项目。待微服务稳定、无bug后全部用户迁移至微服务系统。

以上为背景,实现此方案使用nginx+Lua+Redis灰度发布方案。nginx+lua实现反向代理,获取客户端ip,redis存放ip信息(ip为访问微服务允许的地址).

有两种方案可以实现

第一种:nginx+lua获取用户ip,然后再用lua编写程序直接访问redis集群,查询ip信息返回结果;

第二种:nginx+lua获取用户ip,然后用lua编写程序用http请求到redis缓存服务(单独微服务),缓存服务返回ip地址;

开始是考虑第一种方案,用为openresty没有太好的redis cluster的支持包,资料少;如果用第二种方案redis缓存服务可以单独拎出来,不但可以为nginx使用,还可以为其他服务所用。

两种方案都会说下,不过第一种方案用的是单机redis

我假设都有了OpenResty和redis环境

第一种方案:

在nginx.conf http块中添加代码

//外部配置
include lua.conf;
//新系统地址
upstream new{
      server 192.168.1.103:8081;
}
//老系统地址
upstream old{
      server 192.168.1.103:8080;
}

lua.conf代码

//引入redis模块,只能联单机
local redis = require "resty.redis"
local cache = redis.new()
cache:set_timeout(60000)
//链接
local ok, err = cache.connect(cache, '192.168.19.10', 6379)
// 这里如果链接redis失败,则转发到@old对应的服务器 (传统服务)
if not ok then
    ngx.exec("@old")
    return
end

//如果nginx只有一层分发层,这下面四行代码可以不写
local local_ip = ngx.req.get_headers()["X-Real-IP"]
if local_ip == nil then
    local_ip  = ngx.req.get_headers()["x_forwarded_for"]
end

//从remote_addr变量中拿到客户端ip,同样nginx只有一层的时候此变量为客户端ip,多层不是
if local_ip == nil then
    local_ip = ngx.var.remote_addr
end

//在redis中根据客户端ip获取是否存在值; redis中存放的是key:ip val:ip, 存放的ip访问微服务
local intercept = cache:get(local_ip)
//如果存在则转发到@new对应的服务器(微服务)
if intercept == local_ip then
    ngx.exec("@new")
    return
end
//如果不存在,则转发到@old对应的服务器(传统服务)
ngx.exec("@old")
//关闭客户端
local ok, err = cache.close()
if not ok then
    ngx.say("failed to close:", err)
    return
end

逻辑较简单,但是有些问题1:redis集群要配置多ip,防止宕机问题 2:链接问题,如果有线程池最好了。这里不再多说

第二种方案:

nginx.conf不变

lua.conf 中的redistest.lua 改为httptest.lua

httptest.lua代码如下

//这里缓存服务地址
backend = "http://192.168.1.156:8080"
//缓存服务访问路径
local method = "httptest"
local requestBody = "/"..method
//模块
local http = require("resty.http")
local httpc = http.new()
//设置超时时间
httpc:set_timeout(1000)
//发送请求
local resp, err = httpc:request_uri(backend, {--
    method = "GET", --
    path = requestBody,
    keepalive = false
})
//如果请求失败访问老系统
if not resp then--
    ngx.exec("@old")----
    return--
end
//缓存服务取回ip
local isHave = resp.body
//关闭连接
httpc:close()
//请求ip
local local_ip = ngx.var.remote_addr
//命中则访问微服务
if isHave == local_ip then
    ngx.exec("@new")
    return
end
//没命中访问老系统
ngx.exec("@old")

这里的缓存地址只有一个,实际中有多个,可以采用随机取值去访问一个。超时时间一定要设置,如果缓存系统一直没响应或者缓存服务宕机则直接访问老系统。

例子中在缓存服务中只是存储了真实ip,实际中是存储的IP网段,nginx拿到真实ip字符拆分然后去匹配的。

这里有两点优化没有写出.

1.http可以用连接池代替;

2.可以在nginx内部使用缓存,把命中的ip都存起来,再有链接可以先走本地缓存,再走缓存服务可以提高性能。

目前http没有找到相关连接池,所以一直在非连接池下运行,性能还可以。

另一点直接在nginx中使用了内存进行缓存。

在nginx.conf http块中添加代码

结构为: lua_shared_dict [name][size]

lua_shared_dict rediscache 100m;

更改httptest.lua的代码如下:

backend = "http://192.168.1.156:8080"
//加载共享内存
local cache_ngx = ngx.shared.rediscache
local local_ip = ngx.var.remote_addr
//优先从本地缓存中去取
local cacheip = cache_ngx:get(local_ip)
//本地缓存中不存在,去缓存服务中去取,然后加载到本地缓存
if cacheip == "" or cacheip == nil then
    local http = require("resty.http")
    local httpc = http.new()
    httpc:set_timeout(1000)
    local method = "httptest"
    local requestBody = "/" .. method
    local resp, err = httpc:request_uri(backend, {
        method = "GET",
        path = requestBody,
        keepalive=false
    })
    if not resp then
        ngx.exec("@new")
        return
    end
    cacheip = resp.body
    httpc:close()
    //加载到本地缓存,设置过期时间
    cache_ngx:set(local_ip, cacheip, 10*60)
end
if cacheip == local_ip then
    ngx.exec("@new")
    return
end
ngx.exec("@old")

到此这篇关于nginx+lua+redis 灰度发布实现方案的文章就介绍到这了,更多相关nginx lua redis 灰度内容请搜索编程网(www.lsjlt.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.lsjlt.com)! 

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯