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(proxy-mirror): support mirror requests sample_ratio #4965

Merged
merged 46 commits into from
Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
288ef14
support mirror requests quota
okaybase Sep 2, 2021
488003c
support mirror requests quota
okaybase Sep 2, 2021
13f1968
update test case
okaybase Sep 2, 2021
caa72fc
update test case
okaybase Sep 2, 2021
858aff1
update test case
okaybase Sep 2, 2021
0671562
update test case
okaybase Sep 2, 2021
8242c61
update test case
okaybase Sep 2, 2021
49068c2
update test case
okaybase Sep 2, 2021
20a453f
Merge remote-tracking branch 'origin/master' into feat-n
okaybase Sep 2, 2021
7db849e
mirror percentage
okaybase Sep 2, 2021
704da5c
mirror percentage
okaybase Sep 2, 2021
491771f
mirror requests percentage
okaybase Sep 2, 2021
0595486
update test case
okaybase Sep 2, 2021
37c60b0
rm randomseed
okaybase Sep 3, 2021
dade378
Merge remote-tracking branch 'origin/feat-n' into feat-n
okaybase Sep 3, 2021
6590c3a
mirror requests percentage
okaybase Sep 3, 2021
867d879
use sample_ratio
okaybase Sep 3, 2021
f0363a6
Merge remote-tracking branch 'origin/feat-n' into feat-n
okaybase Sep 3, 2021
494ec37
use sample_ratio
okaybase Sep 3, 2021
f045984
update test case
okaybase Sep 3, 2021
294379d
update test case
okaybase Sep 3, 2021
e25b921
update test case
okaybase Sep 3, 2021
d0671b5
update test case
okaybase Sep 3, 2021
39886b6
update test case
okaybase Sep 3, 2021
1bf99f0
update test case
okaybase Sep 3, 2021
967e18e
update test case
okaybase Sep 3, 2021
c503b5f
update docs
okaybase Sep 7, 2021
03ed5b4
Indent code
okaybase Sep 7, 2021
2bce454
update test case
okaybase Sep 8, 2021
9bfc3ec
update test case
okaybase Sep 9, 2021
7223316
update test case
okaybase Sep 9, 2021
9a2fc60
update test case
okaybase Sep 9, 2021
e241e47
update test case
okaybase Sep 9, 2021
d9770e9
update test case
okaybase Sep 9, 2021
a1f6689
update test case
okaybase Sep 9, 2021
05c268e
update test case
okaybase Sep 9, 2021
57ad5ef
update test case
okaybase Sep 9, 2021
658f108
update test case
okaybase Sep 9, 2021
92eeaa4
update test case
okaybase Sep 9, 2021
06afce2
Merge branch 'master' into feat-n
spacewander Sep 10, 2021
88a5da2
tweak
spacewander Sep 10, 2021
e0686b5
call backend directly
spacewander Sep 10, 2021
db27462
show error
spacewander Sep 10, 2021
d5276c1
just for test
spacewander Sep 10, 2021
d17e5b9
Revert "just for test"
spacewander Sep 10, 2021
fe7034a
roll back to check error log only
spacewander Sep 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions apisix/plugins/proxy-mirror.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
-- limitations under the License.
--
local core = require("apisix.core")

local math_random = math.random
local plugin_name = "proxy-mirror"

local schema = {
Expand All @@ -26,6 +26,12 @@ local schema = {
pattern = [[^http(s)?:\/\/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}]]
.. [[(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:[0-9]{1,5})?$]],
},
sample_ratio = {
type = "number",
minimum = 0.00001,
maximum = 1,
default = 1,
},
},
required = {"host"},
minProperties = 1,
Expand Down Expand Up @@ -53,7 +59,18 @@ function _M.rewrite(conf, ctx)
core.log.info("proxy mirror plugin rewrite phase, conf: ", core.json.delay_encode(conf))

ctx.var.upstream_host = ctx.var.host
ctx.var.upstream_mirror_host = conf.host

if not conf.sample_ratio or conf.sample_ratio == 1 then
ctx.var.upstream_mirror_host = conf.host
else
local val = math_random()
core.log.info("mirror request sample_ratio conf: ", conf.sample_ratio,
", random value: ", val)
if val < conf.sample_ratio then
ctx.var.upstream_mirror_host = conf.host
end
end

end


Expand Down
5 changes: 3 additions & 2 deletions docs/en/latest/plugins/proxy-mirror.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ The proxy-mirror plugin, which provides the ability to mirror client requests.

| Name | Type | Requirement | Default | Valid | Description |
| ---- | ------ | ----------- | ------- | ----- | --------------------------------------------------------------------------------------------------------------------------- |
| host | string | optional | | | Specify a mirror service address, e.g. http://127.0.0.1:9797 (address needs to contain schema: http or https, not URI part) |
| host | string | required | | | Specify a mirror service address, e.g. http://127.0.0.1:9797 (address needs to contain scheme: http or https, and without the path part) |
| sample_ratio | number | optional | 1 | [0.00001, 1] | the sample ratio that requests will be mirrored. |

### Examples

#### Enable the plugin

1: enable the proxy-mirror plugin for a specific route :
example 1: enable the proxy-mirror plugin for a specific route :

```shell
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
Expand Down
1 change: 1 addition & 0 deletions docs/zh/latest/plugins/proxy-mirror.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ title: proxy-mirror
| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
| ---- | ------ | ------ | ------ | ------ | ------------------------------------------------------------------------------------------------------- |
| host | string | 必须 | | | 指定镜像服务地址,例如:http://127.0.0.1:9797(地址中需要包含 schema :http或https,不能包含 URI 部分) |
| sample_ratio | number | 可选 | 1 | [0.00001, 1] | 镜像请求采样率 |

### 示例

Expand Down
12 changes: 12 additions & 0 deletions t/lib/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ local json_decode = require("toolkit.json").decode
local json_encode = require("toolkit.json").encode

local _M = {}
local count = 0


local function inject_headers()
Expand Down Expand Up @@ -425,6 +426,17 @@ function _M._well_known_openid_configuration()
end


function _M.stat_count()
local action = ngx.var.arg_action
if action == "reset" then
count = 0
elseif action == "inc" then
count = count + 1
end
ngx.print(count)
end


-- Please add your fake upstream above
function _M.go()
local action = string.sub(ngx.var.uri, 2)
Expand Down
172 changes: 171 additions & 1 deletion t/plugin/proxy-mirror.t
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_block_preprocessor(sub {
location / {
content_by_lua_block {
local core = require("apisix.core")
local http = require("resty.http")

core.log.info("upstream_http_version: ", ngx.req.http_version())

Expand All @@ -48,8 +49,17 @@ add_block_preprocessor(sub {
core.log.info(v, ": ", headers_tab[v])
end

core.log.info("uri: ", ngx.var.uri)
core.log.info("uri: ", ngx.var.request_uri)
ngx.say("hello world")

local httpc = http.new()
local url = "http://127.0.0.1:1980/stat_count?action=inc"
local res, err = httpc:request_uri(url, {method = "GET"})
if not res then
core.log.error(err)
else
core.log.info("currently stat count is ", res.body)
end
}
}
}
Expand Down Expand Up @@ -445,3 +455,163 @@ GET /t
passed
--- no_error_log
[error]



=== TEST 13: sanity check (invalid sample_ratio)
--- 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": {
"proxy-mirror": {
"host": "http://127.0.0.1:1986",
"sample_ratio": 10
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.print(body)
}
}
--- request
GET /t
--- error_code: 400
--- response_body
{"error_msg":"failed to check the configuration of plugin proxy-mirror err: property \"sample_ratio\" validation failed: expected 10 to be smaller than 1"}
--- no_error_log
[error]



=== TEST 14: set mirror requests sample_ratio to 1
--- 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": {
"proxy-mirror": {
"host": "http://127.0.0.1:1986",
"sample_ratio": 1
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- error_code: 200
--- response_body
passed
--- no_error_log
[error]



=== TEST 15: hit route with sample_ratio 1
--- request
GET /hello?sample_ratio=1
--- error_code: 200
--- response_body
hello world
--- error_log_like eval
qr/uri: \/hello\?sample_ratio=1/



=== TEST 16: set mirror requests sample_ratio to 0.5
--- config
location /t {
content_by_lua_block {
local http = require("resty.http")
local core = require("apisix.core")
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"proxy-mirror": {
"host": "http://127.0.0.1:1986",
"sample_ratio": 0.5
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello"
}]]
)

if code == 200 then
-- reset count
local count = 0
local httpc = http.new()
local url = "http://127.0.0.1:1980/stat_count?action=reset"
local res, err = httpc:request_uri(url, {method = "GET"})
if not res then
core.log.error(err)
else
core.log.info("reset the mirror request stat count to " .. res.body)
count = res.body
end

for i = 1, 200 do
t('/hello?sample_ratio=0.5', ngx.HTTP_GET)
okaybase marked this conversation as resolved.
Show resolved Hide resolved
end

url = "http://127.0.0.1:1980/stat_count"
res, err = httpc:request_uri(url, {method = "GET"})
if not res then
core.log.error(err)
else
core.log.info("the mirror request stat count is " .. res.body)
count = res.body
end
assert(count >= 75 and count <= 125)
elseif code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- error_code: 200
--- response_body
passed
--- error_log_like eval
qr/(uri: \/hello\?sample_ratio=0\.5){75,125}/
--- timeout: 60
okaybase marked this conversation as resolved.
Show resolved Hide resolved