This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 9dde0f262 feat: renew route lrucache when the routes change (#8157)
9dde0f262 is described below
commit 9dde0f26298b14791af0f8b21a9234f1e948bca8
Author: tzssangglass <[email protected]>
AuthorDate: Tue Oct 25 09:31:49 2022 +0800
feat: renew route lrucache when the routes change (#8157)
---
apisix/http/router/radixtree_host_uri.lua | 4 ++
apisix/http/router/radixtree_uri.lua | 5 ++
.../http/router/radixtree_uri_with_parameter.lua | 5 ++
apisix/init.lua | 2 -
apisix/plugins/ai.lua | 78 +++++++++++++++-------
t/plugin/ai.t | 54 +++++++++++++++
6 files changed, 123 insertions(+), 25 deletions(-)
diff --git a/apisix/http/router/radixtree_host_uri.lua
b/apisix/http/router/radixtree_host_uri.lua
index 51a4cdd60..449a6ccdb 100644
--- a/apisix/http/router/radixtree_host_uri.lua
+++ b/apisix/http/router/radixtree_host_uri.lua
@@ -150,7 +150,11 @@ function _M.match(api_ctx)
cached_service_version = service_version
end
+ return _M.matching(api_ctx)
+end
+
+function _M.matching(api_ctx)
core.table.clear(match_opts)
match_opts.method = api_ctx.var.request_method
match_opts.remote_addr = api_ctx.var.remote_addr
diff --git a/apisix/http/router/radixtree_uri.lua
b/apisix/http/router/radixtree_uri.lua
index b438ed8d8..25789a4a3 100644
--- a/apisix/http/router/radixtree_uri.lua
+++ b/apisix/http/router/radixtree_uri.lua
@@ -45,6 +45,11 @@ function _M.match(api_ctx)
return true
end
+ return _M.matching(api_ctx)
+end
+
+
+function _M.matching(api_ctx)
return base_router.match_uri(uri_router, match_opts, api_ctx)
end
diff --git a/apisix/http/router/radixtree_uri_with_parameter.lua
b/apisix/http/router/radixtree_uri_with_parameter.lua
index 257017199..696c74f0b 100644
--- a/apisix/http/router/radixtree_uri_with_parameter.lua
+++ b/apisix/http/router/radixtree_uri_with_parameter.lua
@@ -45,6 +45,11 @@ function _M.match(api_ctx)
return true
end
+ return _M.matching(api_ctx)
+end
+
+
+function _M.matching(api_ctx)
return base_router.match_uri(uri_router, match_opts, api_ctx)
end
diff --git a/apisix/init.lua b/apisix/init.lua
index 883dbd9ab..01f4398cc 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -152,8 +152,6 @@ function _M.http_init_worker()
apisix_upstream.init_worker()
require("apisix.plugins.ext-plugin.init").init_worker()
- -- TODO: need to revisit code layering and avoid similar hacking
- require("apisix.plugins.ai").init_worker()
local_conf = core.config.local_conf()
diff --git a/apisix/plugins/ai.lua b/apisix/plugins/ai.lua
index 699b140b4..46c90ef2e 100644
--- a/apisix/plugins/ai.lua
+++ b/apisix/plugins/ai.lua
@@ -46,11 +46,7 @@ return function(ctx)
end
]]
-local route_lrucache = core.lrucache.new({
- -- TODO: we need to set the cache size by count of routes
- -- if we have done this feature, we need to release the origin lrucache
- count = 512
-})
+local route_lrucache
local schema = {}
@@ -64,27 +60,29 @@ local _M = {
scope = "global",
}
-local orig_router_match
-local orig_handle_upstream = apisix.handle_upstream
-local orig_http_balancer_phase = apisix.http_balancer_phase
+local orig_router_http_matching
+local orig_handle_upstream
+local orig_http_balancer_phase
local default_keepalive_pool = {}
-local function match_route(ctx)
- orig_router_match(ctx)
- return ctx.matched_route or false
+local function create_router_matching_cache(api_ctx)
+ orig_router_http_matching(api_ctx)
+ return core.table.deepcopy(api_ctx)
end
-local function ai_match(ctx)
- local key = get_cache_key_func(ctx)
+local function ai_router_http_matching(api_ctx)
+ local key = get_cache_key_func(api_ctx)
core.log.info("route cache key: ", key)
- local ver = router.router_http.user_routes.conf_version
- local route_cache = route_lrucache(key, ver,
- match_route, ctx)
+ local api_ctx_cache = route_lrucache(key, nil,
+ create_router_matching_cache, api_ctx)
-- if the version has not changed, use the cached route
- if route_cache then
- ctx.matched_route = route_cache
+ if api_ctx then
+ api_ctx.matched_route = api_ctx_cache.matched_route
+ if api_ctx_cache.curr_req_matched then
+ api_ctx.curr_req_matched =
core.table.clone(api_ctx_cache.curr_req_matched)
+ end
end
end
@@ -149,6 +147,18 @@ end
local function routes_analyze(routes)
+ if orig_router_http_matching == nil then
+ orig_router_http_matching = router.router_http.matching
+ end
+
+ if orig_handle_upstream == nil then
+ orig_handle_upstream = apisix.handle_upstream
+ end
+
+ if orig_http_balancer_phase == nil then
+ orig_http_balancer_phase = apisix.http_balancer_phase
+ end
+
local route_flags = core.table.new(0, 16)
local route_up_flags = core.table.new(0, 12)
for _, route in ipairs(routes) do
@@ -224,15 +234,21 @@ local function routes_analyze(routes)
or route_flags["service_id"]
or route_flags["plugin_config_id"]
or global_rules_flag then
- router.router_http.match = orig_router_match
+ router.router_http.matching = orig_router_http_matching
else
core.log.info("use ai plane to match route")
- router.router_http.match = ai_match
+ router.router_http.matching = ai_router_http_matching
+
+ local count = #routes + 3000
+ core.log.info("renew route cache: count=", count)
+ route_lrucache = core.lrucache.new({
+ count = count
+ })
local ok, err = gen_get_cache_key_func(route_flags)
if not ok then
core.log.error("generate get_cache_key_func failed:", err)
- router.router_http.match = orig_router_match
+ router.router_http.matching = orig_router_http_matching
end
end
@@ -279,8 +295,24 @@ function _M.init()
end
-function _M.init_worker()
- orig_router_match = router.router_http.match
+function _M.destroy()
+ -- TODO: add test cases to cover this function
+ -- if the ai plugin is disabled at runtime, all functions replaced by the
ai plugin are restored
+ if orig_router_http_matching then
+ router.router_http.matching = orig_router_http_matching
+ orig_router_http_matching = nil
+ end
+
+ if orig_handle_upstream then
+ apisix.handle_upstream = orig_handle_upstream
+ orig_handle_upstream = nil
+ end
+
+ if orig_http_balancer_phase then
+ apisix.http_balancer_phase = orig_http_balancer_phase
+ orig_http_balancer_phase = nil
+ end
end
+
return _M
diff --git a/t/plugin/ai.t b/t/plugin/ai.t
index f695788ec..6d04c1920 100644
--- a/t/plugin/ai.t
+++ b/t/plugin/ai.t
@@ -875,3 +875,57 @@ done
qr/enable sample upstream/
--- grep_error_log_out
enable sample upstream
+
+
+
+=== TEST 14: renew route cache
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local http = require "resty.http"
+ local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello"
+ for k = 1, 2 do
+ local code, body = t('/apisix/admin/routes/' .. k,
+ ngx.HTTP_PUT,
+ [[{
+ "host": "127.0.0.1",
+ "methods": ["GET"],
+ "plugins": {
+ "proxy-rewrite": {
+ "uri": "/hello"
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello]] .. k .. [["
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+ ngx.sleep(1)
+ for i = 1, 2 do
+ local httpc = http.new()
+ local res, err = httpc:request_uri(uri .. k)
+ assert(res.status == 200)
+ if not res then
+ ngx.log(ngx.ERR, err)
+ return
+ end
+ end
+ end
+ ngx.say("done")
+ }
+ }
+--- response_body
+done
+--- error_log
+renew route cache: count=3001
+renew route cache: count=3002