Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ensure the plugin is always reloaded #4319

Merged
merged 5 commits into from
May 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions apisix/admin/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,22 @@ local function post_reload_plugins()
end


local function sync_local_conf_to_etcd()
core.log.warn("sync local conf to etcd")
local function plugins_eq(old, new)
starsz marked this conversation as resolved.
Show resolved Hide resolved
local old_set = {}
for _, p in ipairs(old) do
old_set[p.name] = p
end

local new_set = {}
for _, p in ipairs(new) do
new_set[p.name] = p
end

return core.table.set_eq(old_set, new_set)
end


local function sync_local_conf_to_etcd(reset)
local local_conf = core.config.local_conf()

local plugins = {}
Expand All @@ -305,6 +318,42 @@ local function sync_local_conf_to_etcd()
})
end

if reset then
local res, err = core.etcd.get("/plugins")
if not res then
core.log.error("failed to get current plugins: ", err)
return
end

if res.status == 404 then
-- nothing need to be reset
return
end

if res.status ~= 200 then
core.log.error("failed to get current plugins, status: ", res.status)
return
end

local stored_plugins = res.body.node.value
local revision = res.body.node.modifiedIndex
if plugins_eq(stored_plugins, plugins) then
core.log.info("plugins not changed, don't need to reset")
return
end

core.log.warn("sync local conf to etcd")

local res, err = core.etcd.atomic_set("/plugins", plugins, nil, revision)
if not res then
core.log.error("failed to set plugins: ", err)
end

return
end

core.log.warn("sync local conf to etcd")

-- need to store all plugins name into one key so that it can be updated atomically
local res, err = core.etcd.set("/plugins", plugins)
if not res then
Expand Down Expand Up @@ -364,7 +413,8 @@ function _M.init_worker()
return
end

sync_local_conf_to_etcd()
-- try to reset the /plugins to the current configuration in the admin
sync_local_conf_to_etcd(true)
end)

if not ok then
Expand Down
31 changes: 0 additions & 31 deletions apisix/plugin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -137,25 +137,6 @@ local function load_plugin(name, plugins_list, is_stream_plugin)
end


local function plugins_eq(old, new)
local eq = core.table.set_eq(old, new)
if not eq then
core.log.info("plugin list changed")
return false
end

for name, plugin in pairs(old) do
eq = core.table.deep_eq(plugin.attr, plugin_attr(name))
if not eq then
core.log.info("plugin_attr of ", name, " changed")
return false
end
end

return true
end


local function load(plugin_names)
local processed = {}
for _, name in ipairs(plugin_names) do
Expand All @@ -164,12 +145,6 @@ local function load(plugin_names)
end
end

-- the same configure may be synchronized more than one
if plugins_eq(local_plugins_hash, processed) then
core.log.info("plugins not changed")
return true
end

core.log.warn("new plugins: ", core.json.delay_encode(processed))

for name in pairs(local_plugins_hash) do
Expand Down Expand Up @@ -212,12 +187,6 @@ local function load_stream(plugin_names)
end
end

-- the same configure may be synchronized more than one
if plugins_eq(stream_local_plugins_hash, processed) then
core.log.info("plugins not changed")
return true
end

core.log.warn("new plugins: ", core.json.delay_encode(processed))

for name in pairs(stream_local_plugins_hash) do
Expand Down
106 changes: 94 additions & 12 deletions t/admin/plugins-reload.t
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ __DATA__
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
-- now the plugin will be loaded twice,
-- one during startup and the other one by reload
local code, _, org_body = t('/apisix/admin/plugins/reload',
ngx.HTTP_PUT)

Expand All @@ -54,15 +56,15 @@ location /t {
GET /t
--- response_body
done
--- grep_error_log eval
qr/sync local conf to etcd/
--- grep_error_log_out
sync local conf to etcd
--- error_log
load plugin times: 1
load plugin times: 1
load plugin times: 2
load plugin times: 2
start to hot reload plugins
start to hot reload plugins
load(): plugins not changed
load_stream(): plugins not changed
load(): plugins not changed
load_stream(): plugins not changed



Expand All @@ -80,8 +82,7 @@ location /t {
automatic = true,
single_item = true,
filter = function(item)
-- called twice before reload,
-- one for worker start, another for sync data from admin
-- called once before reload for sync data from admin
ngx.log(ngx.WARN, "reload plugins on node ",
before_reload and "before reload" or "after reload")
ngx.log(ngx.WARN, require("toolkit.json").encode(item.value))
Expand Down Expand Up @@ -122,7 +123,6 @@ done
qr/reload plugins on node \w+ reload/
--- grep_error_log_out
reload plugins on node before reload
reload plugins on node before reload
reload plugins on node after reload
--- error_log
filter(): [{"name":"jwt-auth"},{"name":"mqtt-proxy","stream":true}]
Expand Down Expand Up @@ -180,6 +180,7 @@ plugin_attr:
local code, _, org_body = t('/apisix/admin/plugins/reload',
ngx.HTTP_PUT)
ngx.say(org_body)
ngx.sleep(0.1)
}
}
--- request
Expand All @@ -196,9 +197,9 @@ example-plugin get plugin attr val: 0
example-plugin get plugin attr val: 1
example-plugin get plugin attr val: 1
example-plugin get plugin attr val: 1
--- error_log
plugin_attr of example-plugin changed
plugins not changed
example-plugin get plugin attr val: 1
example-plugin get plugin attr val: 1
example-plugin get plugin attr val: 1



Expand Down Expand Up @@ -301,3 +302,84 @@ done
qr/Instance report fails/
--- grep_error_log_out
Instance report fails



=== TEST 6: check disabling plugin via etcd
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"echo": {
"body":"hello upstream\n"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed



=== TEST 7: hit
--- yaml_config
apisix:
node_listen: 1984
enable_admin: false
--- request
GET /hello
--- response_body
hello upstream



=== TEST 8: hit after disabling echo
--- yaml_config
apisix:
node_listen: 1984
enable_admin: false
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local etcd = require("apisix.core.etcd")
assert(etcd.set("/plugins", {{name = "jwt-auth"}}))

ngx.sleep(0.2)

local http = require "resty.http"
local httpc = http.new()
local uri = "http://127.0.0.1:" .. ngx.var.server_port
.. "/hello"
local res, err = httpc:request_uri(uri)
if not res then
ngx.say(err)
return
end
ngx.print(res.body)
}
}
--- request
GET /t
--- response_body
hello world
19 changes: 12 additions & 7 deletions t/config-center-yaml/plugin.t
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ load(): new plugins



=== TEST 2: plugins not changed
=== TEST 2: plugins not changed, but still need to reload
--- yaml_config
apisix:
node_listen: 1984
Expand All @@ -104,12 +104,17 @@ plugins:
GET /hello
--- response_body
hello world
--- error_log
load(): loaded plugin and sort by priority: 3000 name: ip-restriction
load(): loaded plugin and sort by priority: 2510 name: jwt-auth
load_stream(): loaded stream plugin and sort by priority: 1000 name: mqtt-proxy
load(): plugins not changed
load_stream(): plugins not changed
--- grep_error_log eval
qr/loaded plugin and sort by priority: \d+ name: [^,]+/
--- grep_error_log_out
loaded plugin and sort by priority: 3000 name: ip-restriction
loaded plugin and sort by priority: 2510 name: jwt-auth
loaded plugin and sort by priority: 3000 name: ip-restriction
loaded plugin and sort by priority: 2510 name: jwt-auth
loaded plugin and sort by priority: 3000 name: ip-restriction
loaded plugin and sort by priority: 2510 name: jwt-auth
loaded plugin and sort by priority: 3000 name: ip-restriction
loaded plugin and sort by priority: 2510 name: jwt-auth



Expand Down