Hello,
先说下场景:
我需要nginx启动的时通过http候拉取配置,之后定期地通过http更新配置,然后根据这些配置信息,通过balancer_by_lua这个接口来转发请求到backend上去。其实就是完成一个简答的dynamic load balancer的功能。
再说下我的思路:
通过init_worker_by_lua来放一个timer.at定时器,定时器的handler里将拉过来的配置写lrucache,然后供content_by_lua和balancer_by_lua用。但是问题来了,首先init_worker_by_lua不支持cosocket,然后我把luasocket.http放到timer.at里就导致worker被阻塞住了,一次请求处理了32s(被我拉配置的逻辑阻塞住了)。
目前的解决办法:
我又拍的同事@timebug 给我建议了一个方案,在init_worker_by_lua里只拉一次配置,不放定时器,然后把定时器放到content_by_lua里,然后被动等待请求触发定时器启动,然后在定时器启动里做一次过期检查,如果配置过期则主动拉去一次配置。
示例代码:
init_worker_by_lua_file
local lrucache = require "resty.lrucache"
local common = require "common"
cache, err = lrucache.new(2)
if not cache then
return error("failed to create the cache: " .. (err or "unknown"))
end
local rules = common.generate_container_rules("10.50.0.166")
cache:set("rules", rules)
ngx.log(ngx.INFO, "load rules successfully")
content_by_lua_file
local rules, err = cache:get("rules")
local common = require "common"
if not rules then
error("faild to get cache: " .. (err or "unknown"))
end
for k,v in pairs(rules) do
ngx.say("add rule: "..k.." "..table.concat(v, " "))
end
local delay = 5
local handler
local lock = false
function handler(premature)
local rules = common.generate_container_rules("10.50.0.166")
cache:set("rules", rules)
ngx.log(ngx.INFO, "load rules successfully")
if premature then
return
end
local ok, err = ngx.timer.at(delay, handler)
if not ok then
ngx.log(ngx.ERR, "failed to create the timer: ", err)
return
end
end
if not lock then
local ok, err = ngx.timer.at(delay, handler)
if not ok then
ngx.log(ngx.ERR, "failed to create the timer: ", err)
return
end
lock = true
end
我想问下大家有没有更好的方案?
我希望nginx启动之后就具备了服务能力,而不是被动等待请求触发定时器。
其实如果init_woker_by_lua能支持cosocket一切就迎刃而解了:)