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

Reply via email to