Skip to content

Commit

Permalink
perf: accelerate the creation of the consumer cache (#11840)
Browse files Browse the repository at this point in the history
Signed-off-by: xuruidong <[email protected]>
  • Loading branch information
xuruidong authored Feb 5, 2025
1 parent 100f290 commit 9e8b0f8
Showing 1 changed file with 81 additions and 38 deletions.
119 changes: 81 additions & 38 deletions apisix/consumer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 9e8b0f8

Please sign in to comment.