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 <[email protected]>
AuthorDate: Wed Feb 5 21:12:13 2025 +0800
perf: accelerate the creation of the consumer cache (#11840)
Signed-off-by: xuruidong <[email protected]>
---
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,