Skip to content

Commit a7c040f

Browse files
okaybasenic-chenlixingwang
authored
feat(plugin): add degradation switch for traffic control plugin (#4774)
Co-authored-by: nic-chen <[email protected]> Co-authored-by: lixingwang <[email protected]>
1 parent 1414cba commit a7c040f

File tree

15 files changed

+198
-7
lines changed

15 files changed

+198
-7
lines changed

apisix/plugins/limit-conn.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ local schema = {
3333
rejected_code = {
3434
type = "integer", minimum = 200, maximum = 599, default = 503
3535
},
36+
allow_degradation = {type = "boolean", default = false}
3637
},
3738
required = {"conn", "burst", "default_conn_delay", "key"}
3839
}

apisix/plugins/limit-conn/init.lua

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ function _M.increase(conf, ctx)
4141
local lim, err = lrucache(conf, nil, create_limit_obj, conf)
4242
if not lim then
4343
core.log.error("failed to instantiate a resty.limit.conn object: ", err)
44+
if conf.allow_degradation then
45+
return
46+
end
4447
return 500
4548
end
4649

@@ -53,7 +56,10 @@ function _M.increase(conf, ctx)
5356
return conf.rejected_code or 503
5457
end
5558

56-
core.log.error("failed to limit req: ", err)
59+
core.log.error("failed to limit conn: ", err)
60+
if conf.allow_degradation then
61+
return
62+
end
5763
return 500
5864
end
5965

apisix/plugins/limit-count.lua

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ local schema = {
4949
type = "string",
5050
enum = {"local", "redis", "redis-cluster"},
5151
default = "local",
52-
}
52+
},
53+
allow_degradation = {type = "boolean", default = false}
5354
},
5455
required = {"count", "time_window"},
5556
dependencies = {
@@ -160,6 +161,9 @@ function _M.access(conf, ctx)
160161
local lim, err = core.lrucache.plugin_ctx(lrucache, ctx, conf.policy, create_limit_obj, conf)
161162
if not lim then
162163
core.log.error("failed to fetch limit.count object: ", err)
164+
if conf.allow_degradation then
165+
return
166+
end
163167
return 500
164168
end
165169

@@ -174,6 +178,9 @@ function _M.access(conf, ctx)
174178
end
175179

176180
core.log.error("failed to limit req: ", err)
181+
if conf.allow_degradation then
182+
return
183+
end
177184
return 500, {error_msg = "failed to limit count: " .. err}
178185
end
179186

apisix/plugins/limit-count/limit-count-redis-cluster.lua

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,11 @@ function _M.new(plugin_name, limit, window, conf)
7474
end
7575

7676
local self = {
77-
limit = limit, window = window, conf = conf,
78-
plugin_name = plugin_name, red_cli =red_cli
77+
limit = limit,
78+
window = window,
79+
conf = conf,
80+
plugin_name = plugin_name,
81+
red_cli = red_cli,
7982
}
8083

8184
return setmetatable(self, mt)

apisix/plugins/limit-count/limit-count-redis.lua

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ local script = [=[
4141
function _M.new(plugin_name, limit, window, conf)
4242
assert(limit > 0 and window > 0)
4343

44-
local self = {limit = limit, window = window, conf = conf,
45-
plugin_name = plugin_name}
44+
local self = {
45+
limit = limit,
46+
window = window,
47+
conf = conf,
48+
plugin_name = plugin_name,
49+
}
4650
return setmetatable(self, mt)
4751
end
4852

apisix/plugins/limit-req.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ local schema = {
3939
nodelay = {
4040
type = "boolean", default = false
4141
},
42+
allow_degradation = {type = "boolean", default = false}
4243
},
4344
required = {"rate", "burst", "key"}
4445
}
@@ -73,6 +74,9 @@ function _M.access(conf, ctx)
7374
create_limit_obj, conf)
7475
if not lim then
7576
core.log.error("failed to instantiate a resty.limit.req object: ", err)
77+
if conf.allow_degradation then
78+
return
79+
end
7680
return 500
7781
end
7882

@@ -96,6 +100,9 @@ function _M.access(conf, ctx)
96100
end
97101

98102
core.log.error("failed to limit req: ", err)
103+
if conf.allow_degradation then
104+
return
105+
end
99106
return 500
100107
end
101108

docs/en/latest/plugins/limit-conn.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Limiting request concurrency plugin.
4343
| only_use_default_delay | boolean | optional | false | [true,false] | enable the strict mode of the latency seconds. If you set this option to `true`, it will run strictly according to the latency seconds you set without additional calculation logic. |
4444
| key | object | required | | ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for", "consumer_name"] | to limit the concurrency level. <br />For example, one can use the host name (or server zone) as the key so that we limit concurrency per host name. Otherwise, we can also use the client address as the key so that we can avoid a single client from flooding our service with too many parallel connections or requests. <br /> Now accept those as key: "remote_addr"(client's IP), "server_addr"(server's IP), "X-Forwarded-For/X-Real-IP" in request header, "consumer_name"(consumer's username). |
4545
| rejected_code | string | optional | 503 | [200,...,599] | returned when the request exceeds `conn` + `burst` will be rejected. |
46+
| allow_degradation | boolean | optional | false | | Whether to enable plugin degradation when the limit-conn function is temporarily unavailable. Allow requests to continue when the value is set to true, default false. |
4647

4748
**Key can be customized by the user, only need to modify a line of code of the plug-in to complete. It is a security consideration that is not open in the plugin.**
4849

docs/en/latest/plugins/limit-count.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Limit request rate by a fixed number of requests in a given time window.
4242
| key | string | optional | "remote_addr" | ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for", "consumer_name", "service_id"] | The user specified key to limit the count. <br /> Now accept those as key: "remote_addr"(client's IP), "server_addr"(server's IP), "X-Forwarded-For/X-Real-IP" in request header, "consumer_name"(consumer's username) and "service_id". |
4343
| rejected_code | integer | optional | 503 | [200,...,599] | The HTTP status code returned when the request exceeds the threshold is rejected, default 503. |
4444
| policy | string | optional | "local" | ["local", "redis", "redis-cluster"] | The rate-limiting policies to use for retrieving and incrementing the limits. Available values are `local`(the counters will be stored locally in-memory on the node), `redis`(counters are stored on a Redis server and will be shared across the nodes, usually use it to do the global speed limit), and `redis-cluster` which works the same as `redis` but with redis cluster. |
45+
| allow_degradation | boolean | optional | false | | Whether to enable plugin degradation when the limit-count function is temporarily unavailable(e.g. redis timeout). Allow requests to continue when the value is set to true, default false. |
4546
| redis_host | string | required for `redis` | | | When using the `redis` policy, this property specifies the address of the Redis server. |
4647
| redis_port | integer | optional | 6379 | [1,...] | When using the `redis` policy, this property specifies the port of the Redis server. |
4748
| redis_password | string | optional | | | When using the `redis` policy, this property specifies the password of the Redis server. |

docs/en/latest/plugins/limit-req.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ limit request rate using the "leaky bucket" method.
4343
| key | string | required | | ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for", "consumer_name"] | the user specified key to limit the rate, now accept those as key: "remote_addr"(client's IP), "server_addr"(server's IP), "X-Forwarded-For/X-Real-IP" in request header, "consumer_name"(consumer's username). |
4444
| rejected_code | integer | optional | 503 | [200,...,599] | The HTTP status code returned when the request exceeds the threshold is rejected. |
4545
| nodelay | boolean | optional | false | | If nodelay flag is true, bursted requests will not get delayed |
46+
| allow_degradation | boolean | optional | false | | Whether to enable plugin degradation when the limit-req function is temporarily unavailable. Allow requests to continue when the value is set to true, default false. |
4647

4748
**Key can be customized by the user, only need to modify a line of code of the plug-in to complete. It is a security consideration that is not open in the plugin.**
4849

docs/zh/latest/plugins/limit-conn.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ title: limit-conn
3333
| only_use_default_delay | boolean | optional | false | [true,false] | 延迟时间的严格模式。 如果设置为`true`的话,将会严格按照设置的时间来进行延迟 |
3434
| key | object | required | | ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for", "consumer_name"] | 用户指定的限制并发级别的关键字,可以是客户端 IP 或服务端 IP。<br />例如,可以使用主机名(或服务器区域)作为关键字,以便限制每个主机名的并发性。 否则,我们也可以使用客户端地址作为关键字,这样我们就可以避免单个客户端用太多的并行连接或请求淹没我们的服务。 <br />当前接受的 key 有:"remote_addr"(客户端 IP 地址), "server_addr"(服务端 IP 地址), 请求头中的"X-Forwarded-For" 或 "X-Real-IP", "consumer_name"(consumer 的 username)。 |
3535
| rejected_code | string | optional | 503 | [200,...,599] | 当请求超过 `conn` + `burst` 这个阈值时,返回的 HTTP 状态码 |
36+
| allow_degradation | boolean | 可选 | false | | 当插件功能临时不可用时是否允许请求继续。当值设置为 true 时则自动允许请求继续,默认值是 false。|
3637

3738
**注:key 是可以被用户自定义的,只需要修改插件的一行代码即可完成。并没有在插件中放开是处于安全的考虑。**
3839

0 commit comments

Comments
 (0)