You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by to...@apache.org on 2021/06/01 05:39:37 UTC
[apisix] branch master updated: feat: allow to set custom timeout
for route (#4340)
This is an automated email from the ASF dual-hosted git repository.
tokers 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 91a048e feat: allow to set custom timeout for route (#4340)
91a048e is described below
commit 91a048e68e5aafe4b32736cf0eca951b727c17a0
Author: Joshua Yang <yx...@gmail.com>
AuthorDate: Tue Jun 1 13:39:29 2021 +0800
feat: allow to set custom timeout for route (#4340)
related #4258
---
apisix/balancer.lua | 17 ++++++++++----
apisix/schema_def.lua | 22 ++++++++++--------
docs/en/latest/admin-api.md | 10 +++++++--
docs/zh/latest/admin-api.md | 6 +++++
t/admin/routes2.t | 37 ++++++++++++++++++++++++++++++
t/node/timeout-upstream.t | 55 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 132 insertions(+), 15 deletions(-)
diff --git a/apisix/balancer.lua b/apisix/balancer.lua
index 3696fa4..d480356 100644
--- a/apisix/balancer.lua
+++ b/apisix/balancer.lua
@@ -134,10 +134,19 @@ end
-- set_balancer_opts will be called in balancer phase and before any tries
-local function set_balancer_opts(ctx)
+local function set_balancer_opts(route, ctx)
local up_conf = ctx.upstream_conf
- if up_conf.timeout then
- local timeout = up_conf.timeout
+
+ -- If the matched route has timeout config, prefer to use the route config.
+ local timeout = nil
+ if route and route.value and route.value.timeout then
+ timeout = route.value.timeout
+ else
+ if up_conf.timeout then
+ timeout = up_conf.timeout
+ end
+ end
+ if timeout then
local ok, err = set_timeouts(timeout.connect, timeout.send,
timeout.read)
if not ok then
@@ -252,7 +261,7 @@ function _M.run(route, ctx)
server = ctx.picked_server
ctx.picked_server = nil
- set_balancer_opts(ctx)
+ set_balancer_opts(route, ctx)
else
-- retry
diff --git a/apisix/schema_def.lua b/apisix/schema_def.lua
index 10318b5..88edd1d 100644
--- a/apisix/schema_def.lua
+++ b/apisix/schema_def.lua
@@ -111,6 +111,17 @@ local desc_def = {
}
+local timeout_def = {
+ type = "object",
+ properties = {
+ connect = {type = "number", exclusiveMinimum = 0},
+ send = {type = "number", exclusiveMinimum = 0},
+ read = {type = "number", exclusiveMinimum = 0},
+ },
+ required = {"connect", "send", "read"},
+}
+
+
local health_checker = {
type = "object",
properties = {
@@ -342,15 +353,7 @@ local upstream_schema = {
type = "integer",
minimum = 0,
},
- timeout = {
- type = "object",
- properties = {
- connect = {type = "number", exclusiveMinimum = 0},
- send = {type = "number", exclusiveMinimum = 0},
- read = {type = "number", exclusiveMinimum = 0},
- },
- required = {"connect", "send", "read"},
- },
+ timeout = timeout_def,
tls = {
type = "object",
properties = {
@@ -495,6 +498,7 @@ _M.route = {
minItems = 1,
uniqueItems = true,
},
+ timeout = timeout_def,
vars = {
type = "array",
},
diff --git a/docs/en/latest/admin-api.md b/docs/en/latest/admin-api.md
index 4e85a49..af97244 100644
--- a/docs/en/latest/admin-api.md
+++ b/docs/en/latest/admin-api.md
@@ -91,6 +91,7 @@ Note: When the `Admin API` is enabled, it will occupy the API prefixed with `/ap
| service_id | False | Service | Binded Service configuration, see [Service](architecture-design/service.md) for more [...]
| plugin_config_id | False, can't be used with `script` | Plugin | Binded plugin config object, see [Plugin Config](architecture-design/plugin-config.md) for more [...]
| labels | False | Match Rules | Key/value pairs to specify attributes [...]
+| timeout | False | Auxiliary | Set the upstream timeout for connecting, sending and receiving messages of the route. This option will overwrite the [timeout](#upstream) option which set in upstream configuration. [...]
| enable_websocket | False | Auxiliary | enable `websocket`(boolean), default `false`. [...]
| status | False | Auxiliary | enable this route, default `1`. [...]
| create_time | False | Auxiliary | epoch timestamp in second, will be created automatically if missing [...]
@@ -117,6 +118,11 @@ Config Example:
"vars": [["http_user", "==", "ios"]], # A list of one or more `[var, operator, val]` elements
"upstream_id": "1", # upstream id, recommended
"upstream": {}, # upstream, not recommended
+ "timeout": { # Set the upstream timeout for connecting, sending and receiving messages of the route.
+ "connect": 3,
+ "send": 3,
+ "read": 3
+ },
"filter_func": "", # User-defined filtering function
}
```
@@ -539,7 +545,7 @@ In addition to the basic complex equalization algorithm selection, APISIX's Upst
|key |optional|This option is only valid if the `type` is `chash`. Find the corresponding node `id` according to `hash_on` and `key`. When `hash_on` is set as `vars`, `key` is the required parameter, for now, it support nginx built-in variables like `uri, server_name, server_addr, request_uri, remote_port, remote_addr, query_string, host, hostname, arg_***`, `arg_***` is arguments in the request line, [Nginx variables list](http://nginx.org/en/docs/varindex.html). When `hash_ [...]
|checks |optional|Configure the parameters of the health check. For details, refer to [health-check](health-check.md).|
|retries |optional|Pass the request to the next upstream using the underlying Nginx retry mechanism, the retry mechanism is enabled by default and set the number of retries according to the number of available backend nodes. If `retries` option is explicitly set, it will override the default value. `0` means disable retry mechanism.|
-|timeout |optional| Set the timeout for connection, sending and receiving messages. |
+|timeout |optional| Set the timeout for connecting, sending and receiving messages. |
|name |optional|Identifies upstream names|
|desc |optional|upstream usage scenarios, and more.|
|pass_host |optional| `host` option when the request is sent to the upstream, can be one of [`pass`, `node`, `rewrite`], the default option is `pass`. `pass`: Pass the client's host transparently to the upstream; `node`: Use the host configured in the node of `upstream`; `rewrite`: Use the value of the configuration `upstream_host`.|
@@ -577,7 +583,7 @@ This feature requires APISIX to run on [APISIX-OpenResty](../how-to-build.md#6-b
{
"id": "1", # id
"retries": 1, # retry times
- "timeout": { # Set the timeout for connection, sending and receiving messages.
+ "timeout": { # Set the timeout for connecting, sending and receiving messages.
"connect":15,
"send":15,
"read":15,
diff --git a/docs/zh/latest/admin-api.md b/docs/zh/latest/admin-api.md
index eb43f81..d8c591a 100644
--- a/docs/zh/latest/admin-api.md
+++ b/docs/zh/latest/admin-api.md
@@ -92,6 +92,7 @@ Admin API 是为 Apache APISIX 服务的一组 API,我们可以将参数传递
| vars | 可选 | 匹配规则 | 由一个或多个`{var, operator, val}`元素组成的列表,类似这样:`{{var, operator, val}, {var, operator, val}, ...}}`。例如:`{"arg_name", "==", "json"}`,表示当前请求参数 `name` 是 `json`。这里的 `var` 与 Nginx 内部自身变量命名是保持一致,所以也可以使用 `request_uri`、`host` 等。更多细节请参考[lua-resty-expr](https://github.com/api7/lua-resty-expr) | {{"arg_name", "==", "json"}, {"arg_age", ">", 18}} |
| filter_func | 可选 | 匹配规则 | 用户自定义的过滤函数。可以使用它来实现特殊场景的匹配要求实现。该函数默认接受一个名为 vars 的输入参数,可以用它来获取 Nginx 变量。 | function(vars) return vars["arg_name"] == "json" end |
| labels | 可选 | 匹配规则 | 标识附加属性的键值对 | {"version":"v2","build":"16","env":"production"} |
+| timeout | 可选 | 辅助 | 为 route 设置 upstream 的连接、发送消息、接收消息的超时时间。这个配置将会覆盖在 upstream 中 配置的 [timeout](#upstream) 选项 | {"connect": 3, "send": 3, "read": 3} |
| enable_websocket | 可选 | 辅助 | 是否启用 `websocket`(boolean), 缺省 `false`. | |
| status | 可选 | 辅助 | 是否启用此路由, 缺省 `1`。 | `1` 表示启用,`0` 表示禁用 |
| create_time | 可选 | 辅助 | 单位为秒的 epoch 时间戳,如果不指定则自动创建 | 1602883670 |
@@ -118,6 +119,11 @@ route 对象 json 配置内容:
"vars": [["http_user", "==", "ios"]], # 由一个或多个 [var, operator, val] 元素组成的列表
"upstream_id": "1", # upstream 对象在 etcd 中的 id ,建议使用此值
"upstream": {}, # upstream 信息对象,建议尽量不要使用
+ "timeout": { # 为 route 设置 upstream 的连接、发送消息、接收消息的超时时间。
+ "connect": 3,
+ "send": 3,
+ "read": 3
+ },
"filter_func": "", # 用户自定义的过滤函数,非必填
}
```
diff --git a/t/admin/routes2.t b/t/admin/routes2.t
index 9d76c94..c472ddb 100644
--- a/t/admin/routes2.t
+++ b/t/admin/routes2.t
@@ -650,3 +650,40 @@ GET /t
{"error_msg":"failed to fetch plugin config info by plugin config id [not_found], response code: 404"}
--- no_error_log
[error]
+
+
+
+=== TEST 18: valid route with timeout
+--- 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,
+ [[{
+ "methods": ["GET"],
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:8080": 1
+ },
+ "type": "roundrobin"
+ },
+ "timeout": {
+ "connect": 3,
+ "send": 3,
+ "read": 3
+ },
+ "uri": "/index.html"
+ }]]
+ )
+
+ ngx.status = code
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
diff --git a/t/node/timeout-upstream.t b/t/node/timeout-upstream.t
index d76f436..38a4a90 100644
--- a/t/node/timeout-upstream.t
+++ b/t/node/timeout-upstream.t
@@ -73,3 +73,58 @@ GET /sleep1
qr/504 Gateway Time-out/
--- error_log
timed out) while reading response header from upstream
+
+
+
+=== TEST 3: set custom timeout for route(overwrite upstream timeout)
+--- 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,
+ [[{
+ "methods": ["GET"],
+ "timeout": {
+ "connect": 0.5,
+ "send": 0.5,
+ "read": 0.5
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin",
+ "timeout": {
+ "connect": 2,
+ "send": 2,
+ "read": 2
+ }
+ },
+ "uri": "/sleep1"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 4: hit routes (timeout)
+--- request
+GET /sleep1
+--- error_code: 504
+--- response_body eval
+qr/504 Gateway Time-out/
+--- error_log
+timed out) while reading response header from upstream