From 925a587ed3f2cf87684290bb31eec9f44b4b9858 Mon Sep 17 00:00:00 2001 From: Yuansheng Date: Mon, 10 Jun 2019 19:48:26 +0800 Subject: [PATCH 1/2] optimize: returns a fetch function when creating a new `lrucache` object, which can be used directly to get cached data. --- .gitignore | 1 + lua/apisix/balancer.lua | 11 +++----- lua/apisix/consumer.lua | 1 - lua/apisix/core/lrucache.lua | 50 +++++++++++++++++++----------------- 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index b06c6b1bcf33..5b1000bf0511 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ logs/*.pid t/servroot go \.* +conf/apisix.uid diff --git a/lua/apisix/balancer.lua b/lua/apisix/balancer.lua index 5fc9dd002d25..86804118b1bf 100644 --- a/lua/apisix/balancer.lua +++ b/lua/apisix/balancer.lua @@ -4,10 +4,7 @@ local balancer = require("ngx.balancer") local upstreams_etcd local error = error local module_name = "balancer" -local lrucache = core.lrucache.new{ - plugin_ttl = 300, - plugin_count = 256 - } +local lrucache_get = core.lrucache.new({ttl = 300, count = 256}) local _M = { @@ -17,8 +14,8 @@ local _M = { local function create_server_picker(typ, nodes) - -- core.log.info("create create_obj, type: ", typ, - -- " nodes: ", core.json.encode(nodes)) + core.log.info("create create_obj, type: ", typ, + " nodes: ", core.json.delay_encode(nodes)) if typ == "roundrobin" then return roundrobin:new(nodes) @@ -61,7 +58,7 @@ function _M.run(route, ctx) key = upstream.type .. "#route_" .. route.value.id end - local server_picker = lrucache:plugin(module_name, key, version, + local server_picker = lrucache_get(key, version, create_server_picker, upstream.type, upstream.nodes) if not server_picker then error("failed to fetch server picker") diff --git a/lua/apisix/consumer.lua b/lua/apisix/consumer.lua index 36768e12f0b1..ea534ad24565 100644 --- a/lua/apisix/consumer.lua +++ b/lua/apisix/consumer.lua @@ -1,6 +1,5 @@ local lrucache = require("apisix.core.lrucache") local config = require("apisix.core.config_etcd") -local log = require("apisix.core.log") local insert_tab = table.insert local consumers local error = error diff --git a/lua/apisix/core/lrucache.lua b/lua/apisix/core/lrucache.lua index c6a1d06e7c69..fc3874911b08 100644 --- a/lua/apisix/core/lrucache.lua +++ b/lua/apisix/core/lrucache.lua @@ -2,7 +2,6 @@ -- only support to cache lua table object local lru_new = require("resty.lrucache").new -local setmetatable = setmetatable -- todo: support to config it in YAML. local GLOBAL_TTL = 60 * 60 -- 60 min local GLOBAL_ITEMS_COUNT = 1024 @@ -82,29 +81,34 @@ function _M.plugin_ctx(plugin_name, api_ctx, create_obj_fun, ...) end -local function _obj_plugin_ctx(self, plugin_name, api_ctx, create_obj_fun, ...) - local key = api_ctx.conf_type .. "#" .. api_ctx.conf_id - return _plugin(self.plugin_count, self.plugin_ttl, plugin_name, key, - api_ctx.conf_version, create_obj_fun, ...) -end - - -local function _obj_plugin(self, plugin_name, key, version, create_obj_fun, ...) - return _plugin(self.plugin_count, self.plugin_ttl, plugin_name, key, - version, create_obj_fun, ...) -end - - function _M.new(opts) - local plugin_count = opts and opts.plugin_count or PLUGIN_ITEMS_COUNT - local plugin_ttl = opts and opts.plugin_ttl or PLUGIN_TTL - - return setmetatable({ - plugin_count = plugin_count, - plugin_ttl = plugin_ttl, - plugin_ctx = _obj_plugin_ctx, - plugin = _obj_plugin, - }, mt) + local item_count = opts and opts.count or GLOBAL_ITEMS_COUNT + local item_ttl = opts and opts.ttl or GLOBAL_TTL + + local lru_obj = lru_new(item_count) + + return function (key, version, create_obj_fun, ...) + local obj, stale_obj = lru_obj:get(key) + if obj and obj._cache_ver == version then + return obj + end + + if stale_obj and stale_obj._cache_ver == version then + lru_obj:set(key, obj, item_ttl) + return stale_obj + end + + local err + obj, err = create_obj_fun(...) + if type(obj) == 'table' then + obj._cache_ver = version + lru_obj:set(key, obj, item_ttl) + else + log.warn('only support to cache Lua table object with lrucache') + end + + return obj, err + end end From 68432592908a8b503a6973bcf3537027832e3b80 Mon Sep 17 00:00:00 2001 From: Yuansheng Date: Mon, 10 Jun 2019 20:25:29 +0800 Subject: [PATCH 2/2] test: added test case for `core.lrucache` library. --- t/core-json.t | 2 + t/core-lrucache.t | 121 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 t/core-lrucache.t diff --git a/t/core-json.t b/t/core-json.t index 441f80050a4f..41518ff564a6 100644 --- a/t/core-json.t +++ b/t/core-json.t @@ -27,6 +27,7 @@ GET /t encode: {"test":"test"} data: test --- no_error_log +[error] @@ -70,3 +71,4 @@ GET /t --- response_body_like eval qr/\{"test":"test","fun":"function: 0x[0-9a-f]+"}/ --- no_error_log +[error] diff --git a/t/core-lrucache.t b/t/core-lrucache.t new file mode 100644 index 000000000000..67ade8a96c60 --- /dev/null +++ b/t/core-lrucache.t @@ -0,0 +1,121 @@ +use t::APISix 'no_plan'; + +repeat_each(1); +no_long_string(); +no_root_location(); +log_level("info"); + +run_tests; + +__DATA__ + +=== TEST 1: sanity +--- config + location /t { + content_by_lua_block { + local core = require("apisix.core") + + local idx = 0 + local function create_obj() + idx = idx + 1 + return {idx = idx} + end + + local obj = core.lrucache.global("key", nil, create_obj) + ngx.say("obj: ", core.json.encode(obj)) + + obj = core.lrucache.global("key", nil, create_obj) + ngx.say("obj: ", core.json.encode(obj)) + + obj = core.lrucache.global("key", "1", create_obj) + ngx.say("obj: ", core.json.encode(obj)) + } + } +--- request +GET /t +--- response_body +obj: {"idx":1} +obj: {"idx":1} +obj: {"idx":2,"_cache_ver":"1"} +--- no_error_log +[error] + + + +=== TEST 2: plugin +--- config + location /t { + content_by_lua_block { + local core = require("apisix.core") + + local idx = 0 + local function create_obj() + idx = idx + 1 + return {idx = idx} + end + + local obj = core.lrucache.plugin("plugin-a", "key", nil, create_obj) + ngx.say("obj: ", core.json.encode(obj)) + + obj = core.lrucache.plugin("plugin-a", "key", nil, create_obj) + ngx.say("obj: ", core.json.encode(obj)) + + obj = core.lrucache.plugin("plugin-a", "key", "1", create_obj) + ngx.say("obj: ", core.json.encode(obj)) + + obj = core.lrucache.plugin("plugin-b", "key", "1", create_obj) + ngx.say("obj: ", core.json.encode(obj)) + } + } +--- request +GET /t +--- response_body +obj: {"idx":1} +obj: {"idx":1} +obj: {"idx":2,"_cache_ver":"1"} +obj: {"idx":3,"_cache_ver":"1"} +--- no_error_log +[error] + + + +=== TEST 3: new +--- config + location /t { + content_by_lua_block { + local core = require("apisix.core") + + local idx = 0 + local function create_obj() + idx = idx + 1 + return {idx = idx} + end + + local lru_get = core.lrucache.new() + + local obj = lru_get("key", nil, create_obj) + ngx.say("obj: ", core.json.encode(obj)) + + obj = lru_get("key", nil, create_obj) + ngx.say("obj: ", core.json.encode(obj)) + + obj = lru_get("key", "1", create_obj) + ngx.say("obj: ", core.json.encode(obj)) + + obj = lru_get("key", "1", create_obj) + ngx.say("obj: ", core.json.encode(obj)) + + obj = lru_get("key-different", "1", create_obj) + ngx.say("obj: ", core.json.encode(obj)) + } + } +--- request +GET /t +--- response_body +obj: {"idx":1} +obj: {"idx":1} +obj: {"idx":2,"_cache_ver":"1"} +obj: {"idx":2,"_cache_ver":"1"} +obj: {"idx":3,"_cache_ver":"1"} +--- no_error_log +[error]