设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间18 现在时间18 缓存数据 从头到尾 我要的只有感情 可没人能给我

从头到尾 我要的只有感情 可没人能给我 -- 情深深雨濛濛

查看: 976|回复: 2

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

[复制链接]

  离线 

TA的专栏

  • 打卡等级:无名新人
  • 打卡总天数:2
  • 打卡月天数:0
  • 打卡总奖励:34
  • 最近打卡:2024-03-31 20:21:47
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
28
主题
24
精华
0
金钱
123
积分
58
注册时间
2023-10-3
最后登录
2025-8-31

发表于 2024-11-25 14:18:26 | 显示全部楼层 |阅读模式
目录


  • 第一种方案:
  • 第二种方案:
背景: 公司要把现有的某传统项目进行微服务化,拆分后要分批次预发布,实现某部分使用户使用微服务模块,其他用户使用传统项目。待微服务稳定、无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块中添加代码
  1. //外部配置
  2. include lua.conf;
  3. //新系统地址
  4. upstream new{
  5.       server 192.168.1.103:8081;
  6. }
  7. //老系统地址
  8. upstream old{
  9.       server 192.168.1.103:8080;
  10. }
复制代码
lua.conf代码
  1. //引入redis模块,只能联单机
  2. local redis = require "resty.redis"
  3. local cache = redis.new()
  4. cache:set_timeout(60000)
  5. //链接
  6. local ok, err = cache.connect(cache, '192.168.19.10', 6379)
  7. // 这里如果链接redis失败,则转发到@old对应的服务器 (传统服务)
  8. if not ok then
  9.     ngx.exec("@old")
  10.     return
  11. end

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

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

  21. //在redis中根据客户端ip获取是否存在值; redis中存放的是key:ip val:ip, 存放的ip访问微服务
  22. local intercept = cache:get(local_ip)
  23. //如果存在则转发到@new对应的服务器(微服务)
  24. if intercept == local_ip then
  25.     ngx.exec("@new")
  26.     return
  27. end
  28. //如果不存在,则转发到@old对应的服务器(传统服务)
  29. ngx.exec("@old")
  30. //关闭客户端
  31. local ok, err = cache.close()
  32. if not ok then
  33.     ngx.say("failed to close:", err)
  34.     return
  35. end
复制代码
逻辑较简单,但是有些问题1:redis集群要配置多ip,防止宕机问题 2:链接问题,如果有线程池最好了。这里不再多说

第二种方案:

nginx.conf不变
lua.conf 中的redistest.lua 改为httptest.lua
httptest.lua代码如下
  1. //这里缓存服务地址
  2. backend = "http://192.168.1.156:8080"
  3. //缓存服务访问路径
  4. local method = "httptest"
  5. local requestBody = "/"..method
  6. //模块
  7. local http = require("resty.http")
  8. local httpc = http.new()
  9. //设置超时时间
  10. httpc:set_timeout(1000)
  11. //发送请求
  12. local resp, err = httpc:request_uri(backend, {--
  13.     method = "GET", --
  14.     path = requestBody,
  15.     keepalive = false
  16. })
  17. //如果请求失败访问老系统
  18. if not resp then--
  19.     ngx.exec("@old")----
  20.     return--
  21. end
  22. //缓存服务取回ip
  23. local isHave = resp.body
  24. //关闭连接
  25. httpc:close()
  26. //请求ip
  27. local local_ip = ngx.var.remote_addr
  28. //命中则访问微服务
  29. if isHave == local_ip then
  30.     ngx.exec("@new")
  31.     return
  32. end
  33. //没命中访问老系统
  34. ngx.exec("@old")
复制代码
这里的缓存地址只有一个,实际中有多个,可以采用随机取值去访问一个。超时时间一定要设置,如果缓存系统一直没响应或者缓存服务宕机则直接访问老系统。
例子中在缓存服务中只是存储了真实ip,实际中是存储的IP网段,nginx拿到真实ip字符拆分然后去匹配的。
这里有两点优化没有写出.
1.http可以用连接池代替;
2.可以在nginx内部使用缓存,把命中的ip都存起来,再有链接可以先走本地缓存,再走缓存服务可以提高性能。
目前http没有找到相关连接池,所以一直在非连接池下运行,性能还可以。
另一点直接在nginx中使用了内存进行缓存。
在nginx.conf http块中添加代码
结构为: lua_shared_dict [name][size]
  1. lua_shared_dict rediscache 100m;
复制代码
更改httptest.lua的代码如下:
  1. backend = "http://192.168.1.156:8080"
  2. //加载共享内存
  3. local cache_ngx = ngx.shared.rediscache
  4. local local_ip = ngx.var.remote_addr
  5. //优先从本地缓存中去取
  6. local cacheip = cache_ngx:get(local_ip)
  7. //本地缓存中不存在,去缓存服务中去取,然后加载到本地缓存
  8. if cacheip == "" or cacheip == nil then
  9.     local http = require("resty.http")
  10.     local httpc = http.new()
  11.     httpc:set_timeout(1000)
  12.     local method = "httptest"
  13.     local requestBody = "/" .. method
  14.     local resp, err = httpc:request_uri(backend, {
  15.         method = "GET",
  16.         path = requestBody,
  17.         keepalive=false
  18.     })
  19.     if not resp then
  20.         ngx.exec("@new")
  21.         return
  22.     end
  23.     cacheip = resp.body
  24.     httpc:close()
  25.     //加载到本地缓存,设置过期时间
  26.     cache_ngx:set(local_ip, cacheip, 10*60)
  27. end
  28. if cacheip == local_ip then
  29.     ngx.exec("@new")
  30.     return
  31. end
  32. ngx.exec("@old")
复制代码
到此这篇关于nginx+lua+redis 灰度发布实现方案的文章就介绍到这了,更多相关nginx lua redis 灰度内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
19
积分
18
注册时间
2022-12-29
最后登录
2022-12-29

发表于 2024-12-28 15:51:13 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
13
积分
6
注册时间
2023-4-20
最后登录
2023-4-20

发表于 昨天 20:30 | 显示全部楼层
路过,支持一下
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表