Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cache) in-memory and shared dict caching strategy #1688

Merged
merged 15 commits into from
Nov 3, 2016
3 changes: 2 additions & 1 deletion kong-0.9.2-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ dependencies = {
"lua-resty-iputils == 0.2.1",
"luacrypto == 0.3.2",
"luasyslog == 1.0.0",
"lua_pack == 1.0.4"
"lua_pack == 1.0.4",
"lua-resty-worker-events == 0.2.0"
}
build = {
type = "builtin",
Expand Down
2 changes: 1 addition & 1 deletion kong/api/routes/cache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ return {
return responses.send_HTTP_NOT_FOUND()
end
}
}
}
10 changes: 7 additions & 3 deletions kong/api/routes/cluster.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
local singletons = require "kong.singletons"
local responses = require "kong.tools.responses"
local constants = require "kong.constants"
local ev = require "resty.worker.events"

local pairs = pairs
local table_insert = table.insert
Expand Down Expand Up @@ -60,7 +62,9 @@ return {
local message_t = self.params

-- The type is always upper case
if message_t.type then
if not message_t or not message_t.type then
return responses.send_HTTP_BAD_REQUEST()
else
message_t.type = string_upper(message_t.type)
end

Expand Down Expand Up @@ -88,9 +92,9 @@ return {
end

-- Trigger event in the node
singletons.events:publish(message_t.type, message_t)
ev.post(constants.CACHE.CLUSTER, message_t.type, message_t)

return responses.send_HTTP_OK()
end
}
}
}
2 changes: 1 addition & 1 deletion kong/conf_loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ local function load(path, custom_conf)
do
local custom_plugins = {}
for i = 1, #conf.custom_plugins do
local plugin_name = conf.custom_plugins[i]
local plugin_name = pl_stringx.strip(conf.custom_plugins[i])
custom_plugins[plugin_name] = true
end
conf.plugins = tablex.merge(constants.PLUGINS_AVAILABLE, custom_plugins, true)
Expand Down
5 changes: 4 additions & 1 deletion kong/constants.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,8 @@ return {
SYSLOG = {
ADDRESS = "kong-hf.mashape.com",
PORT = 61828
},
CACHE = {
CLUSTER = "cluster"
}
}
}
6 changes: 3 additions & 3 deletions kong/core/cluster.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ local function async_autojoin(premature)
end

-- Create retries counter key if it doesn't exist
if not cache.get(cache.autojoin_retries_key()) then
cache.rawset(cache.autojoin_retries_key(), 0)
if not cache.sh_get(cache.autojoin_retries_key()) then
cache.sh_set(cache.autojoin_retries_key(), 0)
end

local autojoin_retries = cache.incr(cache.autojoin_retries_key(), 1) -- Increment retries counter
local autojoin_retries = cache.sh_incr(cache.autojoin_retries_key(), 1) -- Increment retries counter
if (autojoin_retries < ASYNC_AUTOJOIN_RETRIES) then
create_timer(ASYNC_AUTOJOIN_INTERVAL, async_autojoin)
end
Expand Down
10 changes: 5 additions & 5 deletions kong/core/reports.lua
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ ping_handler = function(premature)
elseif elapsed == 0 then
send {
signal = "ping",
requests = cache.get(cache.requests_key()) or 0,
requests = cache.sh_get(cache.requests_key()) or 0,
unique_id = unique_str,
database = singletons.configuration.database
}
cache.rawset(cache.requests_key(), 0)
cache.sh_set(cache.requests_key(), 0)
end

create_ping_timer()
Expand All @@ -137,12 +137,12 @@ return {
-----------------
init_worker = function()
if not enabled then return end
cache.rawset(cache.requests_key(), 0)
cache.sh_set(cache.requests_key(), 0)
create_ping_timer()
end,
log = function()
if not enabled then return end
cache.incr(cache.requests_key(), 1)
cache.sh_incr(cache.requests_key(), 1)
end,
-----------------
-- custom methods
Expand All @@ -153,4 +153,4 @@ return {
get_system_infos = get_system_infos,
send = send,
api_signal = "api"
}
}
25 changes: 24 additions & 1 deletion kong/kong.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ local core = require "kong.core.handler"
local Serf = require "kong.serf"
local utils = require "kong.tools.utils"
local Events = require "kong.core.events"
local constants = require "kong.constants"
local singletons = require "kong.singletons"
local DAOFactory = require "kong.dao.factory"
local plugins_iterator = require "kong.core.plugins_iterator"
Expand Down Expand Up @@ -147,6 +148,28 @@ function Kong.init_worker()
for _, plugin in ipairs(singletons.loaded_plugins) do
plugin.handler:init_worker()
end

local ev = require "resty.worker.events"
local handler = function(data, event, source, pid)
if source and source == constants.CACHE.CLUSTER then
singletons.events:publish(event, data)
end
end

ev.register(handler)

local ok, err = ev.configure {
shm = "process_events", -- defined by "lua_shared_dict"
timeout = 2, -- life time of event data in shm
interval = 1, -- poll interval (seconds)

wait_interval = 0.010, -- wait before retry fetching event data
wait_max = 0.5, -- max wait time before discarding event
}
if not ok then
ngx.log(ngx.ERR, "failed to start event system: ", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be a hard error, not just logging. If this fails, Kong will not be stable, so it must error out and stop.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this is init_worker, and not init. There is no clean way to shutdown a worker and even less to shutdown all of the other workers, too. We could send a sigterm signal to the master process, but we're already out of the CLI at this point, so error handling might no be consistent with the CLI (shutting down other services) out of the box.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could still log this at a higher log level to give it more importance though, like ngx.CRIT or even maybe ngx.ALERT.

return
end
end

function Kong.ssl_certificate()
Expand Down Expand Up @@ -193,4 +216,4 @@ function Kong.log()
core.log.after()
end

return Kong
return Kong
2 changes: 1 addition & 1 deletion kong/meta.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ return {
-- to lua-version's `set()` in the form {from, to}
_DEPENDENCIES = {
nginx = {"1.9.15.1", "1.11.2.1"},
serf = {"0.7.0", "0.7.0"},
serf = {"0.7.0", "0.8.0"},
--resty = {}, -- not version dependent for now
--dnsmasq = {} -- not version dependent for now
}
Expand Down
15 changes: 11 additions & 4 deletions kong/plugins/bot-detection/cache.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local cache = require "kong.tools.database_cache"
local pl_tablex = require "pl.tablex"

local _M = {}

Expand All @@ -7,7 +8,11 @@ local INDEX = "bot_detection_index"
function _M.set(key, value)
cache.set(cache.bot_detection_key(key), value)
local index_keys = cache.get(INDEX)
if not index_keys then index_keys = {} end
if index_keys ~= nil then
index_keys = pl_tablex.deepcopy(index_keys)
else
index_keys = {}
end
index_keys[#index_keys+1] = key
cache.set(INDEX, index_keys)
end
Expand All @@ -18,10 +23,12 @@ end

function _M.reset()
local index_keys = cache.get(INDEX)
for _, key in ipairs(index_keys) do
cache.delete(cache.bot_detection_key(key))
if index_keys ~= nil then
for _, key in ipairs(index_keys) do
cache.delete(cache.bot_detection_key(key))
end
cache.delete(INDEX)
end
cache.delete(INDEX)
end

return _M
10 changes: 5 additions & 5 deletions kong/plugins/rate-limiting/policies.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ return {
local periods = timestamp.get_timestamps(current_timestamp)
for period, period_date in pairs(periods) do
local cache_key = get_local_key(api_id, identifier, period_date, period)
if not cache.rawget(cache_key) then
cache.rawset(cache_key, 0, EXPIRATIONS[period])
if not cache.sh_get(cache_key) then
cache.sh_set(cache_key, 0, EXPIRATIONS[period])
end

local _, err = cache.incr(cache_key, value)
local _, err = cache.sh_incr(cache_key, value)
if err then
ngx_log("[rate-limiting] could not increment counter for period '"..period.."': "..tostring(err))
end
Expand All @@ -39,7 +39,7 @@ return {
usage = function(conf, api_id, identifier, current_timestamp, name)
local periods = timestamp.get_timestamps(current_timestamp)
local cache_key = get_local_key(api_id, identifier, periods[name], name)
local current_metric, err = cache.rawget(cache_key)
local current_metric, err = cache.sh_get(cache_key)
if err then
return nil, err
end
Expand Down Expand Up @@ -138,4 +138,4 @@ return {
return current_metric and current_metric or 0
end
}
}
}
8 changes: 4 additions & 4 deletions kong/plugins/response-ratelimiting/policies.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ return {
local periods = timestamp.get_timestamps(current_timestamp)
for period, period_date in pairs(periods) do
local cache_key = get_local_key(api_id, identifier, period_date, name, period)
if not cache.rawget(cache_key) then
cache.rawset(cache_key, 0, EXPIRATIONS[period])
if not cache.sh_get(cache_key) then
cache.sh_set(cache_key, 0, EXPIRATIONS[period])
end

local _, err = cache.incr(cache_key, value)
local _, err = cache.sh_incr(cache_key, value)
if err then
ngx_log("[rate-limiting] could not increment counter for period '"..period.."': "..tostring(err))
end
Expand All @@ -39,7 +39,7 @@ return {
usage = function(conf, api_id, identifier, current_timestamp, period, name)
local periods = timestamp.get_timestamps(current_timestamp)
local cache_key = get_local_key(api_id, identifier, periods[period], name, period)
local current_metric, err = cache.rawget(cache_key)
local current_metric, err = cache.sh_get(cache_key)
if err then
return nil, err
end
Expand Down
1 change: 1 addition & 0 deletions kong/templates/nginx_kong.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ lua_shared_dict reports_locks 100k;
lua_shared_dict cluster_locks 100k;
lua_shared_dict cluster_autojoin_locks 100k;
lua_shared_dict cache_locks 100k;
lua_shared_dict process_events 1m;
lua_shared_dict cassandra 1m;
lua_shared_dict cassandra_prepared 5m;
lua_socket_log_errors off;
Expand Down
Loading