日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2024/1/23 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 nginx+lua+redis 灰度发布实现方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景: 公司要把現有的某傳統項目進行微服務化,拆分后要分批次預發布,實現某部分使用戶使用微服務模塊,其他用戶使用傳統項目。待微服務穩定、無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 thenngx.exec("@old")return end//如果nginx只有一層分發層,這下面四行代碼可以不寫 local local_ip = ngx.req.get_headers()["X-Real-IP"] if local_ip == nil thenlocal_ip = ngx.req.get_headers()["x_forwarded_for"] end//從remote_addr變量中拿到客戶端ip,同樣nginx只有一層的時候此變量為客戶端ip,多層不是 if local_ip == nil thenlocal_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 thenngx.exec("@new")return end //如果不存在,則轉發到@old對應的服務器(傳統服務) ngx.exec("@old") //關閉客戶端 local ok, err = cache.close() if not ok thenngx.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 thenngx.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 thenlocal http = require("resty.http")local httpc = http.new()httpc:set_timeout(1000)local method = "httptest"local requestBody = "/" .. methodlocal resp, err = httpc:request_uri(backend, {method = "GET",path = requestBody,keepalive=false})if not resp thenngx.exec("@new")returnendcacheip = resp.bodyhttpc:close()//加載到本地緩存,設置過期時間cache_ngx:set(local_ip, cacheip, 10*60) end if cacheip == local_ip thenngx.exec("@new")return end ngx.exec("@old")

?

總結

以上是生活随笔為你收集整理的nginx+lua+redis 灰度发布实现方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。