Skip to content

Commit e462456

Browse files
committed
fix(*) use dedicated shm for rate-limiting plugins
Addresses the issue discussed in #3124 and #3241. This is part of a series of fixes to address those errors. Context ------- In the `local` mode of the rate-limiting plugins, storing the rate-limiting counters in the same shm used by Kong's database cache is too invasive for the underlying shm, especially when the rate-limiting plugins are used with a `seconds` precision. On top of exhausting the database cache slots, this approach also generates some form of fragmentation in the shm. This is due to the side-by-side storage of values with sizes of different orders of magnitude (JSON strings vs. an incremented double) and the LRU eviction mechanism. When the shm is full and LRU kicks-in, it is highly probable that several rate-limiting counters will be evicted (due to their proliferation), thus not freeing enough space to store the retrieved data, causing a `no memory` error to be reported by the shm. Solution -------- Declaring shms that are only used by some plugins is not very elegant. Now, all users (even those not using rate-limiting plugins) have to pay a memory cost (although small). Unfortunately, and in the absence of a more dynamic solution to shm configuration such as a more dynamic templating engine, or a `configure_by_lua` phase, this is the safest solution. Size rationale -------------- Running a script generating similar keys and storing similar values (double) indicates that an shm with 12Mb should be able to store about ~48,000 of those values at once. It is important to remind ourselves that one Consumer/IP address might use more than one key (in fact, one per period configured on the plugin), and both the rate-limiting and response-ratelimiting plugins at once, and they use the same shms. Even considering the above statements, ~48,000 keys per node seems somewhat reasonable, considering keys of `second` precision will most likely fill up the shm and be candidates for LRU eviction. Our concern lies instead around long-lived limits (and thus, keys) set by the user. Additionally, a future improvement upon this will be the setting of the `init_ttl` argument for the rate-limiting keys, which will help **quite considerably** in reducing the footprint of the plugins on the shm. As of this day, this feature has been contributed to ngx_lua but not released yet: openresty/lua-nginx-module#1226 Again, this limit only applies when using the **local** strategy, which also likely means that a load-balancer is distributing traffic to a pool of Kong nodes with some sort of consistent load-balancing technique. Thus considerably reducing the number of concurrent Consumers a given node needs to handle at once. See also -------- Another piece of the fixes for the `no memory` errors resides in the behavior of the database caching module upon a full shm. See: thibaultcha/lua-resty-mlcache#41 This patch reduces the likeliness of a full shm (by a lot!), but does not remove it. The above patch ensures a somewhat still sane behavior would the shm happen to be full again. Fix #3124 Fix #3241
1 parent d6f7904 commit e462456

File tree

5 files changed

+5
-2
lines changed

5 files changed

+5
-2
lines changed

kong/constants.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,6 @@ return {
7373
"kong_process_events",
7474
"kong_cluster_events",
7575
"kong_healthchecks",
76+
"kong_rate_limiting_counters",
7677
},
7778
}

kong/plugins/rate-limiting/policies/init.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ local redis = require "resty.redis"
44
local policy_cluster = require "kong.plugins.rate-limiting.policies.cluster"
55
local reports = require "kong.core.reports"
66
local ngx_log = ngx.log
7-
local shm = ngx.shared.kong_cache
7+
local shm = ngx.shared.kong_rate_limiting_counters
88

99
local pairs = pairs
1010
local fmt = string.format

kong/plugins/response-ratelimiting/policies/init.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ local redis = require "resty.redis"
44
local policy_cluster = require "kong.plugins.response-ratelimiting.policies.cluster"
55
local reports = require "kong.core.reports"
66
local ngx_log = ngx.log
7-
local shm = ngx.shared.kong_cache
7+
local shm = ngx.shared.kong_rate_limiting_counters
88

99
local pairs = pairs
1010
local fmt = string.format

kong/templates/nginx_kong.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ lua_shared_dict kong_cache ${{MEM_CACHE_SIZE}};
3333
lua_shared_dict kong_process_events 5m;
3434
lua_shared_dict kong_cluster_events 5m;
3535
lua_shared_dict kong_healthchecks 5m;
36+
lua_shared_dict kong_rate_limiting_counters 12m;
3637
> if database == "cassandra" then
3738
lua_shared_dict kong_cassandra 5m;
3839
> end

spec/fixtures/custom_nginx.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ http {
4646
lua_shared_dict kong_process_events 5m;
4747
lua_shared_dict kong_cluster_events 5m;
4848
lua_shared_dict kong_healthchecks 5m;
49+
lua_shared_dict kong_rate_limiting_counters 12m;
4950
> if database == "cassandra" then
5051
lua_shared_dict kong_cassandra 5m;
5152
> end

0 commit comments

Comments
 (0)