nginx+lua+redis 灰度發(fā)布實現(xiàn)方案
背景: 公司要把現(xiàn)有的某傳統(tǒng)項目進行微服務(wù)化,拆分后要分批次預(yù)發(fā)布,實現(xiàn)某部分使用戶使用微服務(wù)模塊,其他用戶使用傳統(tǒng)項目。待微服務(wù)穩(wěn)定、無bug后全部用戶遷移至微服務(wù)系統(tǒng)。
以上為背景,實現(xiàn)此方案使用nginx+lua+redis灰度發(fā)布方案。nginx+lua實現(xiàn)反向代理,獲取客戶端ip,redis存放ip信息(ip為訪問微服務(wù)允許的地址).
有兩種方案可以實現(xiàn)
第一種:nginx+lua獲取用戶ip,然后再用lua編寫程序直接訪問redis集群,查詢ip信息返回結(jié)果;
第二種:nginx+lua獲取用戶ip,然后用lua編寫程序用http請求到redis緩存服務(wù)(單獨微服務(wù)),緩存服務(wù)返回ip地址;
開始是考慮第一種方案,用為openresty沒有太好的redis cluster的支持包,資料少;如果用第二種方案redis緩存服務(wù)可以單獨拎出來,不但可以為nginx使用,還可以為其他服務(wù)所用。
兩種方案都會說下,不過第一種方案用的是單機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)單機 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對應(yīng)的服務(wù)器 (傳統(tǒng)服務(wù)) if not ok then ngx.exec("@old") return end //如果nginx只有一層分發(fā)層,這下面四行代碼可以不寫 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中根據(jù)客戶端ip獲取是否存在值; redis中存放的是key:ip val:ip, 存放的ip訪問微服務(wù) local intercept = cache:get(local_ip) //如果存在則轉(zhuǎn)發(fā)到@new對應(yīng)的服務(wù)器(微服務(wù)) if intercept == local_ip then ngx.exec("@new") return end //如果不存在,則轉(zhuǎn)發(fā)到@old對應(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
邏輯較簡單,但是有些問題1:redis集群要配置多ip,防止宕機問題 2:鏈接問題,如果有線程池最好了。這里不再多說
第二種方案:
nginx.conf不變
lua.conf 中的redistest.lua 改為httptest.lua
httptest.lua代碼如下
//這里緩存服務(wù)地址 backend = "http://192.168.1.156:8080" //緩存服務(wù)訪問路徑 local method = "httptest" local requestBody = "/"..method //模塊 local http = require("resty.http") local httpc = http.new() //設(shè)置超時時間 httpc:set_timeout(1000) //發(fā)送請求 local resp, err = httpc:request_uri(backend, {-- method = "GET", -- path = requestBody, keepalive = false }) //如果請求失敗訪問老系統(tǒng) if not resp then-- ngx.exec("@old")---- return-- end //緩存服務(wù)取回ip local isHave = resp.body //關(guān)閉連接 httpc:close() //請求ip local local_ip = ngx.var.remote_addr //命中則訪問微服務(wù) if isHave == local_ip then ngx.exec("@new") return end //沒命中訪問老系統(tǒng) ngx.exec("@old")
這里的緩存地址只有一個,實際中有多個,可以采用隨機取值去訪問一個。超時時間一定要設(shè)置,如果緩存系統(tǒng)一直沒響應(yīng)或者緩存服務(wù)宕機則直接訪問老系統(tǒng)。
例子中在緩存服務(wù)中只是存儲了真實ip,實際中是存儲的IP網(wǎng)段,nginx拿到真實ip字符拆分然后去匹配的。
這里有兩點優(yōu)化沒有寫出.
1.http可以用連接池代替;
2.可以在nginx內(nèi)部使用緩存,把命中的ip都存起來,再有鏈接可以先走本地緩存,再走緩存服務(wù)可以提高性能。
目前http沒有找到相關(guān)連接池,所以一直在非連接池下運行,性能還可以。
另一點直接在nginx中使用了內(nèi)存進行緩存。
在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è)置過期時間 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ā)布實現(xiàn)方案的文章就介紹到這了,更多相關(guān)nginx lua redis 灰度內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
nginx關(guān)閉favicon.ico、robots.txt日志記錄配置
這篇文章主要介紹了nginx關(guān)閉favicon.ico、robots.txt日志記錄配置,同時提供了不允許訪問某些隱藏文件的配置方法,需要的朋友可以參考下2014-05-05nginx如何使用openssl自簽名實現(xiàn)https登錄
這篇文章主要介紹了nginx使用openssl自簽名實現(xiàn)https登錄,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08nginx設(shè)置X-Frame-Options的字段選擇
本文主要介紹了X-Frame-Options選項的三個值,包含DENY、SAMEORIGIN和ALLOW-FROM uri,具有一定的參考價值,感興趣的可以了解一下2024-12-12配置Nginx實現(xiàn)訪問本地靜態(tài)資源的完整指南
Nginx 是一個高性能的 HTTP 服務(wù)器和反向代理服務(wù)器,廣泛用于靜態(tài)資源的托管和負載均衡,在開發(fā)和生產(chǎn)環(huán)境中,我們常常需要使用 Nginx 來提供本地靜態(tài)資源的訪問,本文將詳細介紹如何配置 Nginx 以便訪問本地靜態(tài)資源,需要的朋友可以參考下2024-08-08