This is an automated email from the ASF dual-hosted git repository.

membphis 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 9e8b0f800 perf: accelerate the creation of the consumer cache (#11840)
9e8b0f800 is described below

commit 9e8b0f800af04734c7ede20a2cbe35b8cd2df6ad
Author: xuruidong <xuruid...@gmail.com>
AuthorDate: Wed Feb 5 21:12:13 2025 +0800

    perf: accelerate the creation of the consumer cache (#11840)
    
    Signed-off-by: xuruidong <xuruid...@gmail.com>
---
 apisix/consumer.lua | 119 +++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 81 insertions(+), 38 deletions(-)

diff --git a/apisix/consumer.lua b/apisix/consumer.lua
index ff00406ca..0ec39d719 100644
--- a/apisix/consumer.lua
+++ b/apisix/consumer.lua
@@ -36,6 +36,11 @@ local lrucache = core.lrucache.new({
     ttl = 300, count = 512
 })
 
+-- Please calculate and set the value of the "consumers_count_for_lrucache"
+-- variable based on the number of consumers in the current environment,
+-- taking into account the appropriate adjustment coefficient.
+local consumers_count_for_lrucache = 4096
+
 local function remove_etcd_prefix(key)
     local prefix = ""
     local local_conf = config_local.local_conf()
@@ -80,7 +85,53 @@ local function filter_consumers_list(data_list)
     return list
 end
 
-local function plugin_consumer()
+local plugin_consumer
+do
+    local consumers_id_lrucache = core.lrucache.new({
+            count = consumers_count_for_lrucache
+        })
+
+local function construct_consumer_data(val, plugin_config)
+    -- if the val is a Consumer, clone it to the local consumer;
+    -- if the val is a Credential, to get the Consumer by consumer_name and 
then clone
+    -- it to the local consumer.
+    local consumer
+    if is_credential_etcd_key(val.key) then
+        local consumer_name = 
get_consumer_name_from_credential_etcd_key(val.key)
+        local the_consumer = consumers:get(consumer_name)
+        if the_consumer and the_consumer.value then
+            consumer = core.table.clone(the_consumer.value)
+            consumer.modifiedIndex = the_consumer.modifiedIndex
+            consumer.credential_id = get_credential_id_from_etcd_key(val.key)
+        else
+            -- Normally wouldn't get here:
+            -- it should belong to a consumer for any credential.
+            core.log.error("failed to get the consumer for the credential,",
+                " a wild credential has appeared!",
+                " credential key: ", val.key, ", consumer name: ", 
consumer_name)
+            return nil, "failed to get the consumer for the credential"
+        end
+    else
+        consumer = core.table.clone(val.value)
+        consumer.modifiedIndex = val.modifiedIndex
+    end
+
+    -- if the consumer has labels, set the field custom_id to it.
+    -- the custom_id is used to set in the request headers to the upstream.
+    if consumer.labels then
+        consumer.custom_id = consumer.labels["custom_id"]
+    end
+
+    -- Note: the id here is the key of consumer data, which
+    -- is 'username' field in admin
+    consumer.consumer_name = consumer.id
+    consumer.auth_conf = plugin_config
+
+    return consumer
+end
+
+
+function plugin_consumer()
     local plugins = {}
 
     if consumers.values == nil then
@@ -101,46 +152,21 @@ local function plugin_consumer()
                 if not plugins[name] then
                     plugins[name] = {
                         nodes = {},
+                        len = 0,
                         conf_version = consumers.conf_version
                     }
                 end
 
-                -- if the val is a Consumer, clone it to the local consumer;
-                -- if the val is a Credential, to get the Consumer by 
consumer_name and then clone
-                -- it to the local consumer.
-                local consumer
-                if is_credential_etcd_key(val.key) then
-                    local consumer_name = 
get_consumer_name_from_credential_etcd_key(val.key)
-                    local the_consumer = consumers:get(consumer_name)
-                    if the_consumer and the_consumer.value then
-                        consumer = core.table.clone(the_consumer.value)
-                        consumer.modifiedIndex = the_consumer.modifiedIndex
-                        consumer.credential_id = 
get_credential_id_from_etcd_key(val.key)
-                    else
-                        -- Normally wouldn't get here:
-                        -- it should belong to a consumer for any credential.
-                        core.log.error("failed to get the consumer for the 
credential,",
-                            " a wild credential has appeared!",
-                            " credential key: ", val.key, ", consumer name: ", 
consumer_name)
-                        goto CONTINUE
-                    end
-                else
-                    consumer = core.table.clone(val.value)
-                    consumer.modifiedIndex = val.modifiedIndex
-                end
-
-                -- if the consumer has labels, set the field custom_id to it.
-                -- the custom_id is used to set in the request headers to the 
upstream.
-                if consumer.labels then
-                    consumer.custom_id = consumer.labels["custom_id"]
+                local consumer = consumers_id_lrucache(val.value.id .. name,
+                        val.modifiedIndex, construct_consumer_data, val, 
config)
+                if consumer == nil then
+                    goto CONTINUE
                 end
 
-                -- Note: the id here is the key of consumer data, which
-                -- is 'username' field in admin
-                consumer.consumer_name = consumer.id
-                consumer.auth_conf = config
+                plugins[name].len = plugins[name].len + 1
+                core.table.insert(plugins[name].nodes, plugins[name].len,
+                                    consumer)
                 core.log.info("consumer:", core.json.delay_encode(consumer))
-                core.table.insert(plugins[name].nodes, consumer)
             end
         end
 
@@ -150,6 +176,9 @@ local function plugin_consumer()
     return plugins
 end
 
+end
+
+
 _M.filter_consumers_list = filter_consumers_list
 
 function _M.get_consumer_key_from_credential_key(key)
@@ -190,20 +219,34 @@ function _M.consumers()
 end
 
 
-local function create_consume_cache(consumers_conf, key_attr)
+local create_consume_cache
+do
+    local consumer_lrucache = core.lrucache.new({
+            count = consumers_count_for_lrucache
+        })
+
+local function fill_consumer_secret(consumer)
+    local new_consumer = core.table.clone(consumer)
+    new_consumer.auth_conf = secret.fetch_secrets(new_consumer.auth_conf, 
false)
+    return new_consumer
+end
+
+
+function create_consume_cache(consumers_conf, key_attr)
     local consumer_names = {}
 
     for _, consumer in ipairs(consumers_conf.nodes) do
         core.log.info("consumer node: ", core.json.delay_encode(consumer))
-        local new_consumer = core.table.clone(consumer)
-        new_consumer.auth_conf = secret.fetch_secrets(new_consumer.auth_conf, 
true,
-                                                        
new_consumer.auth_conf, "")
+        local new_consumer = consumer_lrucache(consumer, nil,
+                                fill_consumer_secret, consumer)
         consumer_names[new_consumer.auth_conf[key_attr]] = new_consumer
     end
 
     return consumer_names
 end
 
+end
+
 
 function _M.consumers_kv(plugin_name, consumer_conf, key_attr)
     local consumers = lrucache("consumers_key#" .. plugin_name, 
consumer_conf.conf_version,

Reply via email to