Skip to content
14 changes: 12 additions & 2 deletions apisix/plugins/limit-conn/limit-conn-redis.lua
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ function _M.incoming(self, key, commit)
if not red then
return red, err
end
return util.incoming(self, red, key, commit)
local delay, incoming_err = util.incoming(self, red, key, commit)
local ok, err = red:set_keepalive(conf.keepalive_timeout, conf.keepalive_pool)
if not ok then
core.log.error("set keepalive failed:", err)
end
return delay, incoming_err
end


Expand All @@ -64,7 +69,12 @@ local function leaving_thread(premature, self, key, req_latency)
if not red then
return red, err
end
return util.leaving(self, red, key, req_latency)
local conn, leaving_err = util.leaving(self, red, key, req_latency)
local ok, err = red:set_keepalive(conf.keepalive_timeout, conf.keepalive_pool)
if not ok then
core.log.error("set keepalive failed:", err)
end
return conn, leaving_err
end


Expand Down
2 changes: 1 addition & 1 deletion apisix/plugins/limit-count/limit-count-redis.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function _M.incoming(self, key, cost)
local remaining = res[1]
ttl = res[2]

local ok, err = red:set_keepalive(10000, 100)
local ok, err = red:set_keepalive(conf.keepalive_timeout, conf.keepalive_pool)
if not ok then
return nil, err, ttl
end
Expand Down
10 changes: 7 additions & 3 deletions apisix/plugins/limit-req/limit-req-redis.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
local redis = require("apisix.utils.redis")
local setmetatable = setmetatable
local util = require("apisix.plugins.limit-req.util")

local setmetatable = setmetatable
local core = require("apisix.core")


local _M = {version = 0.1}
Expand Down Expand Up @@ -47,7 +46,12 @@ function _M.incoming(self, key, commit)
return red, err
end

return util.incoming(self, red, key, commit)
local delay, incoming_err = util.incoming(self, red, key, commit)
local ok, err = red:set_keepalive(conf.keepalive_timeout, conf.keepalive_pool)
if not ok then
core.log.error("set keepalive failed:", err)
end
return delay, incoming_err
end


Expand Down
12 changes: 12 additions & 0 deletions apisix/utils/redis-schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ local policy_to_additional_properties = {
redis_ssl_verify = {
type = "boolean", default = false,
},
keepalive_timeout = {
type = "integer", minimum = 1000, default = 10000
},
keepalive_pool = {
type = "integer", minimum = 1, default = 100
}
},
required = {"redis_host"},
},
Expand Down Expand Up @@ -69,6 +75,12 @@ local policy_to_additional_properties = {
redis_cluster_ssl_verify = {
type = "boolean", default = false,
},
keepalive_timeout = {
type = "integer", minimum = 1000, default = 10000
},
keepalive_pool = {
type = "integer", minimum = 1, default = 100
}
},
required = {"redis_cluster_nodes", "redis_cluster_name"},
},
Expand Down
4 changes: 4 additions & 0 deletions apisix/utils/rediscluster.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ local function new_redis_cluster(conf, dict_name)
local config = {
name = conf.redis_cluster_name,
serv_list = {},
keepalive_timeout = conf.keepalive_timeout, --redis connection pool idle timeout
keepalive_cons = conf.keepalive_pool, --redis connection pool size
connect_timeout = conf.redis_timeout,
read_timeout = conf.redis_timeout,
send_timeout = conf.redis_timeout,
auth = conf.redis_password,
dict_name = dict_name,
connect_opts = {
Expand Down
2 changes: 2 additions & 0 deletions docs/zh/latest/plugins/limit-conn.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ description: limit-conn 插件通过管理并发连接来限制请求速率。
| redis_ssl_verify | boolean | 否 | false | | 如果为 true,则在 `policy` 为 `redis` 时验证服务器 SSL 证书。|
| redis_database | integer | 否 | 0 | >= 0 | 当 `policy` 为 `redis` 时,Redis 中的数据库编号。|
| redis_timeout | integer | 否 | 1000 | [1,...] | 当 `policy` 为 `redis` 或 `redis-cluster` 时,Redis 超时值(以毫秒为单位)。 |
| keepalive_timeout | integer | 否 | 10000 | ≥ 1000 | 当 `policy` 为 `redis` 或 `redis-cluster` 时,与 `redis` 或 `redis-cluster` 的空闲连接超时时间,单位为毫秒。|
| keepalive_pool | integer | 否 | 100 | ≥ 1 | 当 `policy` 为 `redis` 或 `redis-cluster` 时,与 `redis` 或 `redis-cluster` 的连接池最大连接数。|
| redis_cluster_nodes | array[string] | 否 | | | 具有至少两个地址的 Redis 群集节点列表。当 policy 为 redis-cluster 时必填。 |
redis_cluster_name | string | 否 | | | | Redis 集群的名称。当 `policy` 为 `redis-cluster` 时必须使用。|
| redis_cluster_ssl | boolean | 否 | false | | 如果为 `true`,当 `policy` 为 `redis-cluster`时,使用 SSL 连接 Redis 集群。|
Expand Down
2 changes: 2 additions & 0 deletions docs/zh/latest/plugins/limit-count.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ description: limit-count 插件使用固定窗口算法,通过给定时间间
| redis_ssl_verify | boolean | 否 | false | | 如果为 true,则在 `policy` 为 `redis` 时验证服务器 SSL 证书。|
| redis_database | integer | 否 | 0 | >= 0 | 当 `policy` 为 `redis` 时,Redis 中的数据库编号。|
| redis_timeout | integer | 否 | 1000 | [1,...] | 当 `policy` 为 `redis` 或 `redis-cluster` 时,Redis 超时值(以毫秒为单位)。 |
| keepalive_timeout | integer | 否 | 10000 | ≥ 1000 | 当 `policy` 为 `redis` 或 `redis-cluster` 时,与 `redis` 或 `redis-cluster` 的空闲连接超时时间,单位为毫秒。|
| keepalive_pool | integer | 否 | 100 | ≥ 1 | 当 `policy` 为 `redis` 或 `redis-cluster` 时,与 `redis` 或 `redis-cluster` 的连接池最大连接数。|
| redis_cluster_nodes | array[string] | 否 | | | 具有至少两个地址的 Redis 群集节点列表。当 policy 为 redis-cluster 时必填。 |
redis_cluster_name | string | 否 | | | | Redis 集群的名称。当 `policy` 为 `redis-cluster` 时必须使用。|
| redis_cluster_ssl | boolean | 否 | false | | 如果为 `true`,当 `policy` 为 `redis-cluster`时,使用 SSL 连接 Redis 集群。|
Expand Down
2 changes: 2 additions & 0 deletions docs/zh/latest/plugins/limit-req.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ description: limit-req 插件使用漏桶算法来限制请求的数量并允许
| redis_ssl_verify | boolean | 否 | false | | 如果为 true,则在 `policy` 为 `redis` 时验证服务器 SSL 证书。|
| redis_database | integer | 否 | 0 | >= 0 | 当 `policy` 为 `redis` 时,Redis 中的数据库编号。|
| redis_timeout | integer | 否 | 1000 | [1,...] | 当 `policy` 为 `redis` 或 `redis-cluster` 时,Redis 超时值(以毫秒为单位)。 |
| keepalive_timeout | integer | 否 | 10000 | ≥ 1000 | 当 `policy` 为 `redis` 或 `redis-cluster` 时,与 `redis` 或 `redis-cluster` 的空闲连接超时时间,单位为毫秒。|
| keepalive_pool | integer | 否 | 100 | ≥ 1 | 当 `policy` 为 `redis` 或 `redis-cluster` 时,与 `redis` 或 `redis-cluster` 的连接池最大连接数。|
| redis_cluster_nodes | array[string] | 否 | | | 具有至少两个地址的 Redis 群集节点列表。当 policy 为 redis-cluster 时必填。 |
redis_cluster_name | string | 否 | | | | Redis 集群的名称。当 `policy` 为 `redis-cluster` 时必须使用。|
| redis_cluster_ssl | boolean | 否 | false | | 如果为 `true`,当 `policy` 为 `redis-cluster`时,使用 SSL 连接 Redis 集群。|
Expand Down
42 changes: 42 additions & 0 deletions t/plugin/limit-conn-redis-cluster.t
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ status:503, count:4
"127.0.0.1:7002",
"127.0.0.1:7000"
],
"keepalive_timeout" :10000,
"keepalive_pool" : 100,
"redis_cluster_name": "redis-cluster-2",
"redis_cluster_ssl": true,
"redis_cluster_ssl_verify": false
Expand Down Expand Up @@ -337,3 +339,43 @@ GET /test_concurrency
--- response_body
status:200, count:6
status:503, count:4



=== TEST 10: check redis cluster keepalive param
--- config
location /t {
content_by_lua_block {
local lim_conn_redis_cluster = require("apisix.plugins.limit-conn.limit-conn-redis-cluster")
local conf = {
conn = 5,
burst = 1,
default_conn_delay = 0.1,
rejected_code = 503,
key = "remote_addr",
policy = "redis-cluster",
redis_cluster_nodes = {
"127.0.0.1:7001",
"127.0.0.1:7002",
"127.0.0.1:7000"
},
keepalive_timeout = 10000,
keepalive_pool = 100,
redis_cluster_name = "redis-cluster-2",
redis_cluster_ssl = true,
redis_cluster_ssl_verify = false
}
local lim = lim_conn_redis_cluster.new("limit-conn", conf, 5, 1)
local redis_conf = lim.red_cli.config
if redis_conf.keepalive_timeout ==10000 and redis_conf.keepalive_cons == 100 then
ngx.say("keepalive set success")
return
end
ngx.say("keepalive set abnormal,keepalive_timeout:",
redis_conf.keepalive_timeout,",keepalive_cons:",redis_conf.keepalive_cons)
}
}
--- request
GET /t
--- response_body
keepalive set success
47 changes: 47 additions & 0 deletions t/plugin/limit-conn-redis.t
Original file line number Diff line number Diff line change
Expand Up @@ -808,3 +808,50 @@ GET /test_concurrency
--- response_body
status:200, count:5
status:503, count:5



=== TEST 26: verify redis keepalive
--- extra_init_by_lua
local limit_conn = require("apisix.plugins.limit-conn.limit-conn-redis")
local core = require("apisix.core")

limit_conn.origin_incoming = limit_conn.incoming
limit_conn.incoming = function(self, key, commit)
local redis = require("resty.redis")
local conf = self.conf
local delay, err = self:origin_incoming(key, commit)
if not delay then
ngx.say("limit fail: ", err)
return delay, err
end

-- verify connection reused time
local red,err = redis:new()
if err then
core.log.error("failed to create redis cli: ", err)
ngx.say("failed to create redis cli: ", err)
return nil,err
end
red:set_timeout(1000)
local ok, err = red:connect(conf.redis_host, conf.redis_port)
if not ok then
core.log.error("failed to connect: ", err)
ngx.say("failed to connect: ", err)
return nil,err
end
local reused_time, err = red:get_reused_times()
if reused_time == 0 then
core.log.error("redis connection is not keepalive")
ngx.say("redis connection is not keepalive")
return nil,err
end

red:close()
ngx.say("redis connection has set keepalive")
return delay,err
end
--- request
GET /limit_conn
--- response_body
redis connection has set keepalive
36 changes: 36 additions & 0 deletions t/plugin/limit-count-redis-cluster3.t
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ passed
"key": "remote_addr",
"policy": "redis-cluster",
"redis_timeout": 1001,
"keepalive_timeout" :10000,
"keepalive_pool" : 100,
"redis_cluster_nodes": [
"$ENV://REDIS_NODE_0",
"$ENV://REDIS_NODE_1"
Expand Down Expand Up @@ -183,3 +185,37 @@ passed
["GET /hello", "GET /hello", "GET /hello"]
--- error_code eval
[200, 200, 503]



=== TEST 6: check redis cluster keepalive param
--- config
location /t {
content_by_lua_block {
local lim_count_redis_cluster = require("apisix.plugins.limit-count.limit-count-redis-cluster")
local conf = {
count = 2,
time_window = 60,
rejected_code = 503,
key = "remote_addr",
policy = "redis-cluster",
redis_timeout = 1001,
keepalive_timeout = 10000,
keepalive_pool = 100,
redis_cluster_nodes = {
"127.0.0.1:5000"
},
redis_cluster_name = "redis-cluster-1"
}
local lim = lim_count_redis_cluster.new("limit-count", 2, 60, conf)
local redis_conf = lim.red_cli.config
if redis_conf.keepalive_timeout ==10000 and redis_conf.keepalive_cons == 100 then
ngx.say("keepalive set success")
return
end
ngx.say("keepalive set abnormal,keepalive_timeout:",
redis_conf.keepalive_timeout,",keepalive_cons:",redis_conf.keepalive_cons)
}
}
--- response_body
keepalive set success
90 changes: 89 additions & 1 deletion t/plugin/limit-count-redis4.t
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ remaining: 1
"count": 2,
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
"key": "$remote_addr testcase_4_2",
"key_type":"var_combination",
"policy": "redis",
"redis_host": "$ENV://REDIS_HOST"
}
Expand Down Expand Up @@ -134,3 +135,90 @@ passed
["GET /hello", "GET /hello", "GET /hello"]
--- error_code eval
[200, 200, 503]



=== TEST 4: set route for keepalive test
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"uri": "/hello",
"plugins": {
"limit-count": {
"count": 20,
"time_window": 1,
"rejected_code": 503,
"key": "remote_addr",
"show_limit_quota_header":false,
"policy": "redis",
"redis_host": "$ENV://REDIS_HOST"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
}
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- response_body
passed



=== TEST 5: verify redis keepalive
--- extra_init_by_lua
local limit_count = require("apisix.plugins.limit-count.limit-count-redis")
local core = require("apisix.core")

limit_count.origin_incoming = limit_count.incoming
limit_count.incoming = function(self, key, commit)
local redis = require("resty.redis")
local conf = self.conf
local delay, err = self:origin_incoming(key, commit)
if not delay then
ngx.say("limit fail: ", err)
return delay, err
end

-- verify connection reused time
local red,err = redis:new()
if err then
core.log.error("failed to create redis cli: ", err)
ngx.say("failed to create redis cli: ", err)
return nil,err
end
red:set_timeout(1000)
local ok, err = red:connect(conf.redis_host, conf.redis_port)
if not ok then
core.log.error("failed to connect: ", err)
ngx.say("failed to connect: ", err)
return nil,err
end
local reused_time, err = red:get_reused_times()
if reused_time == 0 then
core.log.error("redis connection is not keepalive")
ngx.say("redis connection is not keepalive")
return nil,err
end

red:close()
ngx.say("redis connection has set keepalive")
return delay,err
end
--- request
GET /hello
--- response_body
redis connection has set keepalive
Loading
Loading