nginx+lua+redis 灰度發(fā)布實(shí)現(xiàn)方案
背景: 公司要把現(xiàn)有的某傳統(tǒng)項(xiàng)目進(jìn)行微服務(wù)化,拆分后要分批次預(yù)發(fā)布,實(shí)現(xiàn)某部分使用戶使用微服務(wù)模塊,其他用戶使用傳統(tǒng)項(xiàng)目。待微服務(wù)穩(wěn)定、無(wú)bug后全部用戶遷移至微服務(wù)系統(tǒng)。
以上為背景,實(shí)現(xiàn)此方案使用nginx+lua+redis灰度發(fā)布方案。nginx+lua實(shí)現(xiàn)反向代理,獲取客戶端ip,redis存放ip信息(ip為訪問(wèn)微服務(wù)允許的地址).
有兩種方案可以實(shí)現(xiàn)
第一種:nginx+lua獲取用戶ip,然后再用lua編寫(xiě)程序直接訪問(wèn)redis集群,查詢ip信息返回結(jié)果;
第二種:nginx+lua獲取用戶ip,然后用lua編寫(xiě)程序用http請(qǐng)求到redis緩存服務(wù)(單獨(dú)微服務(wù)),緩存服務(wù)返回ip地址;
開(kāi)始是考慮第一種方案,用為openresty沒(méi)有太好的redis cluster的支持包,資料少;如果用第二種方案redis緩存服務(wù)可以單獨(dú)拎出來(lái),不但可以為nginx使用,還可以為其他服務(wù)所用。
兩種方案都會(huì)說(shuō)下,不過(guò)第一種方案用的是單機(jī)redis
我假設(shè)都有了OpenResty和redis環(huán)境
第一種方案:
在nginx.conf http塊中添加代碼
//外部配置
include lua.conf;
//新系統(tǒng)地址
upstream new{
server 192.168.1.103:8081;
}
//老系統(tǒng)地址
upstream old{
server 192.168.1.103:8080;
}lua.conf代碼
//引入redis模塊,只能聯(lián)單機(jī)
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失敗,則轉(zhuǎn)發(fā)到@old對(duì)應(yīng)的服務(wù)器 (傳統(tǒng)服務(wù))
if not ok then
ngx.exec("@old")
return
end
//如果nginx只有一層分發(fā)層,這下面四行代碼可以不寫(xiě)
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只有一層的時(shí)候此變量為客戶端ip,多層不是
if local_ip == nil then
local_ip = ngx.var.remote_addr
end
//在redis中根據(jù)客戶端ip獲取是否存在值; redis中存放的是key:ip val:ip, 存放的ip訪問(wèn)微服務(wù)
local intercept = cache:get(local_ip)
//如果存在則轉(zhuǎn)發(fā)到@new對(duì)應(yīng)的服務(wù)器(微服務(wù))
if intercept == local_ip then
ngx.exec("@new")
return
end
//如果不存在,則轉(zhuǎn)發(fā)到@old對(duì)應(yīng)的服務(wù)器(傳統(tǒng)服務(wù))
ngx.exec("@old")
//關(guān)閉客戶端
local ok, err = cache.close()
if not ok then
ngx.say("failed to close:", err)
return
end
邏輯較簡(jiǎn)單,但是有些問(wèn)題1:redis集群要配置多ip,防止宕機(jī)問(wèn)題 2:鏈接問(wèn)題,如果有線程池最好了。這里不再多說(shuō)
第二種方案:
nginx.conf不變
lua.conf 中的redistest.lua 改為httptest.lua
httptest.lua代碼如下
//這里緩存服務(wù)地址
backend = "http://192.168.1.156:8080"
//緩存服務(wù)訪問(wèn)路徑
local method = "httptest"
local requestBody = "/"..method
//模塊
local http = require("resty.http")
local httpc = http.new()
//設(shè)置超時(shí)時(shí)間
httpc:set_timeout(1000)
//發(fā)送請(qǐng)求
local resp, err = httpc:request_uri(backend, {--
method = "GET", --
path = requestBody,
keepalive = false
})
//如果請(qǐng)求失敗訪問(wèn)老系統(tǒng)
if not resp then--
ngx.exec("@old")----
return--
end
//緩存服務(wù)取回ip
local isHave = resp.body
//關(guān)閉連接
httpc:close()
//請(qǐng)求ip
local local_ip = ngx.var.remote_addr
//命中則訪問(wèn)微服務(wù)
if isHave == local_ip then
ngx.exec("@new")
return
end
//沒(méi)命中訪問(wèn)老系統(tǒng)
ngx.exec("@old")
這里的緩存地址只有一個(gè),實(shí)際中有多個(gè),可以采用隨機(jī)取值去訪問(wèn)一個(gè)。超時(shí)時(shí)間一定要設(shè)置,如果緩存系統(tǒng)一直沒(méi)響應(yīng)或者緩存服務(wù)宕機(jī)則直接訪問(wèn)老系統(tǒng)。
例子中在緩存服務(wù)中只是存儲(chǔ)了真實(shí)ip,實(shí)際中是存儲(chǔ)的IP網(wǎng)段,nginx拿到真實(shí)ip字符拆分然后去匹配的。
這里有兩點(diǎn)優(yōu)化沒(méi)有寫(xiě)出.
1.http可以用連接池代替;
2.可以在nginx內(nèi)部使用緩存,把命中的ip都存起來(lái),再有鏈接可以先走本地緩存,再走緩存服務(wù)可以提高性能。
目前http沒(méi)有找到相關(guān)連接池,所以一直在非連接池下運(yùn)行,性能還可以。
另一點(diǎn)直接在nginx中使用了內(nèi)存進(jìn)行緩存。
在nginx.conf http塊中添加代碼
結(jié)構(gòu)為: lua_shared_dict [name][size]
lua_shared_dict rediscache 100m;
更改httptest.lua的代碼如下:
backend = "http://192.168.1.156:8080"
//加載共享內(nèi)存
local cache_ngx = ngx.shared.rediscache
local local_ip = ngx.var.remote_addr
//優(yōu)先從本地緩存中去取
local cacheip = cache_ngx:get(local_ip)
//本地緩存中不存在,去緩存服務(wù)中去取,然后加載到本地緩存
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()
//加載到本地緩存,設(shè)置過(guò)期時(shí)間
cache_ngx:set(local_ip, cacheip, 10*60)
end
if cacheip == local_ip then
ngx.exec("@new")
return
end
ngx.exec("@old")到此這篇關(guān)于nginx+lua+redis 灰度發(fā)布實(shí)現(xiàn)方案的文章就介紹到這了,更多相關(guān)nginx lua redis 灰度內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- nginx+lua+redis實(shí)現(xiàn)降級(jí)的示例代碼
- Nginx + lua 實(shí)現(xiàn)WAF的詳細(xì)過(guò)程
- Nginx Lua Waf 插件一鍵部署的操作示例
- Nginx如何安裝配置Lua支持
- Nginx Lua 根據(jù)參數(shù)請(qǐng)求轉(zhuǎn)發(fā)的實(shí)現(xiàn)
- Nginx Lua 緩存配置的實(shí)現(xiàn)步驟
- 使用nginx+lua進(jìn)行token鑒權(quán)的方法
- Nginx中使用Lua腳本與圖片的縮略圖處理的實(shí)現(xiàn)
- Nginx配置中使用Lua腳本的實(shí)現(xiàn)步驟
相關(guān)文章
nginx禁止直接通過(guò)ip進(jìn)行訪問(wèn)并跳轉(zhuǎn)到自定義500頁(yè)面的操作
這篇文章主要介紹了nginx禁止直接通過(guò)ip進(jìn)行訪問(wèn)并跳轉(zhuǎn)到自定義500頁(yè)面的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
Nginx重定向后請(qǐng)求參數(shù)丟失的原因分析及解決方案
在日常開(kāi)發(fā)和運(yùn)維中,我們經(jīng)常會(huì)遇到需要使用 Nginx 進(jìn)行反向代理的場(chǎng)景,但在配置 proxy_pass 時(shí),有時(shí)候可能會(huì)遇到請(qǐng)求參數(shù)丟失的問(wèn)題,在這篇文章中,我們將會(huì)詳細(xì)探討這個(gè)問(wèn)題并給出幾種解決方案,需要的朋友可以參考下2023-11-11
Ubuntu安裝Nginx全過(guò)程(在線安裝&源碼編譯安裝)
介紹了在Ubuntu 20.04上安裝Nginx的兩種方式:apt安裝和源碼編譯安裝,apt安裝簡(jiǎn)單,但模塊有限;源碼編譯安裝可以自定義模塊,更靈活2025-03-03
nginx 隱藏版本號(hào)與WEB服務(wù)器信息的解決方法
這篇文章主要介紹了nginx 隱藏版本號(hào)與WEB服務(wù)器信息的解決方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11
Nginx Rewrite規(guī)則與使用介紹和技巧實(shí)例
這篇文章主要介紹了Nginx Rewrite規(guī)則與使用介紹和技巧實(shí)例,本文講解了正則表達(dá)式匹配、文件及目錄匹配、flag標(biāo)記、Nginx Rewrite相關(guān)指令等內(nèi)容,需要的朋友可以參考下2015-01-01
使用nginx搭建點(diǎn)播和直播流媒體服務(wù)器的方法步驟
本篇文章主要介紹了使用nginx搭建點(diǎn)播和直播流媒體服務(wù)器的方法步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
Nginx配置動(dòng)態(tài)代理后通過(guò)curl訪問(wèn)報(bào)403問(wèn)題
本文主要介紹了Nginx配置動(dòng)態(tài)代理后通過(guò)curl訪問(wèn)報(bào)403問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
如何實(shí)現(xiàn)Nginx同一端口同時(shí)支持http與https協(xié)議
最近有一個(gè)需求,需要讓一個(gè)端口的http服務(wù)支持https訪問(wèn),本文就來(lái)介紹一下如何實(shí)現(xiàn)Nginx同一端口同時(shí)支持http與https協(xié)議,感興趣的可以了解一下2023-11-11
詳解Nginx的超時(shí)keeplive_timeout配置步驟
Nginx 處理的每個(gè)請(qǐng)求均有相應(yīng)的超時(shí)設(shè)置,本文主要介紹了Nginx的超時(shí)keeplive_timeout配置步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
開(kāi)發(fā)環(huán)境服務(wù)器vs生產(chǎn)環(huán)境服務(wù)器:開(kāi)發(fā)與生產(chǎn)須分明詳解
開(kāi)發(fā)環(huán)境服務(wù)器(如Vite)和生產(chǎn)環(huán)境服務(wù)器(如Nginx和Node.js)在職責(zé)和工作方式上存在顯著差異,開(kāi)發(fā)環(huán)境服務(wù)器專注于快速開(kāi)發(fā)和調(diào)試,而生產(chǎn)環(huán)境服務(wù)器則強(qiáng)調(diào)穩(wěn)定性和高并發(fā)處理,Vite適合開(kāi)發(fā)環(huán)境,而Nginx和Node.js更適合生產(chǎn)環(huán)境2025-01-01

