You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by me...@apache.org on 2020/10/27 02:44:52 UTC

[apisix] branch master updated: feat:The limit-conn plugin supports 'consumer_name' field (#2415)

This is an automated email from the ASF dual-hosted git repository.

membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new e2f450f  feat:The limit-conn plugin supports 'consumer_name' field (#2415)
e2f450f is described below

commit e2f450fa1a3e62c67b2c28b7c204e750dfc437b9
Author: JinChen <36...@users.noreply.github.com>
AuthorDate: Tue Oct 27 10:44:44 2020 +0800

    feat:The limit-conn plugin supports 'consumer_name' field (#2415)
    
    The limit-conn plugin supports the` consumer_name` field
    The method of PR is referred: #2333
---
 apisix/plugins/limit-conn.lua   |   2 +-
 doc/plugins/limit-conn.md       |   2 +-
 doc/zh-cn/plugins/limit-conn.md |   2 +-
 t/plugin/limit-conn.t           | 242 +++++++++++++++++++++++++++++++++++++++-
 4 files changed, 244 insertions(+), 4 deletions(-)

diff --git a/apisix/plugins/limit-conn.lua b/apisix/plugins/limit-conn.lua
index ca8ca3c..2b80a3b 100644
--- a/apisix/plugins/limit-conn.lua
+++ b/apisix/plugins/limit-conn.lua
@@ -28,7 +28,7 @@ local schema = {
         default_conn_delay = {type = "number", exclusiveMinimum = 0},
         key = {type = "string",
             enum = {"remote_addr", "server_addr", "http_x_real_ip",
-                    "http_x_forwarded_for"},
+                    "http_x_forwarded_for", "consumer_name"},
         },
         rejected_code = {type = "integer", minimum = 200, default = 503},
     },
diff --git a/doc/plugins/limit-conn.md b/doc/plugins/limit-conn.md
index 0b3c7c7..5a50629 100644
--- a/doc/plugins/limit-conn.md
+++ b/doc/plugins/limit-conn.md
@@ -37,7 +37,7 @@ Limiting request concurrency plugin.
 | conn               | integer | required    |         | [0,...]                                                                  | the maximum number of concurrent requests allowed. Requests exceeding this ratio (and below `conn` + `burst`) will get delayed to conform to this threshold.                                                                                                                                                                                                             [...]
 | burst              | integer | required    |         | [0,...]                                                                  | the number of excessive concurrent requests (or connections) allowed to be delayed.                                                                                                                                                                                                                                                                                      [...]
 | default_conn_delay | number  | required    |         | [0,...]                                                                  | the default processing latency of a typical connection (or request).                                                                                                                                                                                                                                                                                                     [...]
-| key                | object  | required    |         | ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for"] | 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"(c [...]
+| 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 [...]
 | rejected_code      | string  | optional    | 503     | [200,...]                                                                | returned when the request exceeds `conn` + `burst` will be rejected.                                                                                                                                                                                                                                                                                                     [...]
 
 **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.**
diff --git a/doc/zh-cn/plugins/limit-conn.md b/doc/zh-cn/plugins/limit-conn.md
index ff5371f..3f1cac1 100644
--- a/doc/zh-cn/plugins/limit-conn.md
+++ b/doc/zh-cn/plugins/limit-conn.md
@@ -30,7 +30,7 @@
 | conn               | integer | required |        | [0,...]                                                                  | 允许的最大并发请求数。超过 `conn` 的限制、但是低于 `conn` + `burst` 的请求,将被延迟处理。                                                                                                                                                                                                                                                                                            |
 | burst              | integer | required |        | [0,...]                                                                  | 允许被延迟处理的并发请求数。                                                                                                                                                                                                                                                                                                                                                          |
 | default_conn_delay | number  | required |        | [0,...]                                                                  | 默认的典型连接(或请求)的处理延迟时间。                                                                                                                                                                                                                                                                                                                                                |
-| key                | object  | required |        | ["remote_addr", "server_addr", "http_x_real_ip", "http_x_forwarded_for"] | 用户指定的限制并发级别的关键字,可以是客户端IP或服务端IP。<br>例如,可以使用主机名(或服务器区域)作为关键字,以便限制每个主机名的并发性。 否则,我们也可以使用客户端地址作为关键字,这样我们就可以避免单个客户端用太多的并行连接或请求淹没我们的服务。 <br>当前接受的 key 有:"remote_addr"(客户端IP地址), "server_addr"(服务端 IP 地址), 请求头中的"X-Forwarded-For" 或 "X-Real-IP"。 |
+| 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)。 |
 | rejected_code      | string  | optional | 503    | [200,...]                                                                | 当请求超过 `conn` + `burst` 这个阈值时,返回的 HTTP状态码                                                                                                                                                                                                                                                                                                                             |
 
 **注:key 是可以被用户自定义的,只需要修改插件的一行代码即可完成。并没有在插件中放开是处于安全的考虑。**
diff --git a/t/plugin/limit-conn.t b/t/plugin/limit-conn.t
index 4401857..b178875 100644
--- a/t/plugin/limit-conn.t
+++ b/t/plugin/limit-conn.t
@@ -974,7 +974,6 @@ GET /test_concurrency
                     ngx.say(err)
                 end
             end
-
             ngx.say("done")
         }
     }
@@ -986,3 +985,244 @@ property "default_conn_delay" validation failed: expected 0 to be sctrictly grea
 done
 --- no_error_log
 [error]
+
+
+
+
+=== TEST 26: create consumer and bind key-auth plugin
+--- config 
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/consumers',
+                ngx.HTTP_PUT,
+                [[{
+                    "username": "consumer_jack",
+                    "plugins": {
+                        "key-auth": {
+                            "key": "auth-jack"
+                        }
+                    }
+                }]]
+                )
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 27: create route and enable plugin 'key-auth' 
+--- 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,
+                 [[{
+                        "plugins": {
+                            "key-auth": {},
+                            "limit-conn": {
+                                "conn": 100,
+                                "burst": 50,
+                                "default_conn_delay": 0.1,
+                                "rejected_code": 503,
+                                "key": "consumer_name"
+                            }
+                        },
+                        "upstream": {
+                            "nodes": {
+                                "127.0.0.1:1980": 1
+                            },
+                            "type": "roundrobin"
+                        },
+                        "uri": "/limit_conn"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 28: not exceeding the burst
+--- config
+    location /access_root_dir {
+        content_by_lua_block {
+            local port = ngx.var.server_port
+            local httpc = require "resty.http"
+            local hc = httpc:new()
+
+            local res, err = hc:request_uri('http://127.0.0.1:' .. port .. '/limit_conn', {
+                headers = {["apikey"] = "auth-jack"}
+            })
+            if res then
+                ngx.exit(res.status)
+            end
+        }
+    }
+
+    location /test_concurrency {
+        content_by_lua_block {
+            local reqs = {}
+            for i = 1, 10 do
+                reqs[i] = { "/access_root_dir" }
+            end
+            local resps = { ngx.location.capture_multi(reqs) }
+            for i, resp in ipairs(resps) do
+                ngx.say(resp.status)
+            end
+        }
+    }
+--- request
+GET /test_concurrency
+--- timeout: 10s
+--- response_body
+200
+200
+200
+200
+200
+200
+200
+200
+200
+200
+--- error_log_like eval
+qr/limit key: consumer_jackroute&consumer\d+/
+
+
+
+=== TEST 29: update plugin "limit-conn" configuration "conn" and "burst"
+--- 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,
+                 [[{
+                        "plugins": {
+                            "key-auth": {},
+                            "limit-conn": {
+                                "conn": 2,
+                                "burst": 1,
+                                "default_conn_delay": 0.1,
+                                "rejected_code": 503,
+                                "key": "consumer_name"
+                            }
+                        },
+                        "upstream": {
+                            "nodes": {
+                                "127.0.0.1:1980": 1
+                            },
+                            "type": "roundrobin"
+                        },
+                        "uri": "/limit_conn"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 30: exceeding the burst
+--- config
+    location /access_root_dir {
+        content_by_lua_block {
+            local port = ngx.var.server_port
+            local httpc = require "resty.http"
+            local hc = httpc:new()
+
+            local res, err = hc:request_uri('http://127.0.0.1:' .. port .. '/limit_conn', {
+                headers = {["apikey"] = "auth-jack"}
+            })
+            if res then
+                ngx.exit(res.status)
+            end
+        }
+    }
+
+    location /test_concurrency {
+        content_by_lua_block {
+            local reqs = {}
+            for i = 1, 10 do
+                reqs[i] = { "/access_root_dir" }
+            end
+            local resps = { ngx.location.capture_multi(reqs) }
+            for i, resp in ipairs(resps) do
+                ngx.say(resp.status)
+            end
+        }
+    }
+--- request
+GET /test_concurrency
+--- timeout: 10s
+--- response_body
+200
+200
+200
+503
+503
+503
+503
+503
+503
+503
+--- error_log_like eval
+qr/limit key: consumer_jackroute&consumer\d+/
+
+
+
+=== TEST 31: plugin limit-conn uses the wrong value of key
+--- config
+    location /t {
+        content_by_lua_block {
+            local plugin = require("apisix.plugins.limit-conn")
+            local ok, err = plugin.check_schema({
+                conn = 1, 
+                default_conn_delay = 0.1, 
+                rejected_code = 503, 
+                key = 'consumer_name'
+                    })
+            if not ok then
+                ngx.say(err)
+            end
+            ngx.say("done")
+        }
+    }
+--- request
+GET /t
+--- response_body
+property "burst" is required
+done
+--- no_error_log
+[error]