需求
項目需要在nginx的lua腳本中,訪問nacos來獲取redis的配置。記錄一下過程。
ngx_lua模塊中使用共享內存字典
在nginx
的conf.d
中增加一行,開啟共享內存空間
lua_shared_dict DICT 1m;
然后是在lua中使用這個空間
-- 獲取內存中的參數
local ip, ipFlags = ngx.shared.DICT:get(ipStr)
-- 設置參數值
success, err, forcible = ngx.shared.DICT:set(ipStr, ip)
ngx_lua中發送http請求
依賴lua-resty-http
庫
local http = require "resty.http"
local httpc = http.new()
local url = "http://ip:端口/......"
local resStr --響應結果
local res, err = httpc:request_uri(url, {
method = "POST",
--args = str,
body = str,
headers = {
["Content-Type"] = "application/json",
}
})
if not res then
ngx.log(ngx.WARN,"failed to request: ", err)
return resStr
end
--請求之后,狀態碼
ngx.status = res.status
if ngx.status ~= 200 then
ngx.log(ngx.WARN,"非200狀態,ngx.status:"..ngx.status)
return resStr
end
--響應的內容
resStr = res.body
解析返回值
從nacos中獲取的返回值是這個樣子的
spring:
redis:
database: 0
host: 1.1.1.1
password: 123
port: 6379
用正則來匹配
ip = string.match(resStr, "host:%s(.-)%c")
port = string.match(resStr, "port:%s(.+)")
passwd = string.match(resStr, "password:%s(.-)%c")
database = string.match(resStr, "database:%s(.-)%c")
這里port的正則跟別的不一樣是因為它是最后一行了,他后面沒有換行符
訪問dns服務器獲取ip
因為nacos
的地址每個環境也不一樣,所以要用domain來進行訪問,但是lua-resty-http
默認不支持對domain的解析,只能使用lua-resty-dns
來進行解析,再發送請求。
local resolver = require "resty.dns.resolver"
local http = require "resty.http"
function get_domain_ip_by_dns( domain )
-- 這里寫死了google的域名服務ip,要根據實際情況做調整(例如放到指定配置或數據庫中)
local dns = "8.8.8.8"
local r, err = resolver:new{
nameservers = {dns, {dns, 53} },
retrans = 5, -- 5 retransmissions on receive timeout
timeout = 2000, -- 2 sec
}
if not r then
return nil, "failed to instantiate the resolver: " .. err
end
local answers, err = r:query(domain)
if not answers then
return nil, "failed to query the DNS server: " .. err
end
if answers.errcode then
return nil, "server returned error code: " .. answers.errcode .. ": " .. answers.errstr
end
for i, ans in ipairs(answers) do
if ans.address then
return ans.address
end
end
return nil, "not founded"
end
-- 使用
local domain_ip, err = get_domain_ip_by_dns("nacos-0.nacos-headless.default.svc.cluster.local")
這里還有個需要注意的地方,在k8s的pods里直接 ping nacos-headless.default
是可用解析到的,但是在ngx_lua里卻報 name error
,只有使用 nacos-0.nacos-headless.default.svc.cluster.local
才能正確獲取到
nslookup nacos-headless.default 10.0.0.2
Server: 10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local
Name: nacos-headless.default
Address 1: 10.240.1.1 nacos-0.nacos-headless.default.svc.cluster.local
Address 2: 10.240.2.2 nacos-2.nacos-headless.default.svc.cluster.local
Address 3: 10.240.3.3 nacos-1.nacos-headless.default.svc.cluster.local