workflow
workflow 插件支持根据使用 APISIX 表达式定义的规则集,对客户端流量有条件地执行用户自定义操作,从而实现细粒度流量管理。
如果你希望应用更复杂的匹配条件和操作,请参阅 traffic-label 插件。
示例
以下示例演示了如何在不同场景下使用 workflow 插件。
按条件返回 HTTP 状态码
以下示例演示了一个具有单个匹配条件和单个关联操作的简单规则,用于按条件返回 HTTP 状态码。
创建一个启用 workflow 插件的路由:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "workflow-route",
"uri": "/anything/*",
"plugins": {
"workflow":{
"rules":[
{
"case":[
["uri", "==", "/anything/rejected"]
],
"actions":[
[
"return",
{"code": 403}
]
]
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /anything/*
name: workflow-route
plugins:
workflow:
rules:
- case:
- ["uri", "==", "/anything/rejected"]
actions:
- - return
- code: 403
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: workflow-plugin-config
spec:
plugins:
- name: workflow
config:
rules:
- case:
- ["uri", "==", "/anything/rejected"]
actions:
- - return
- code: 403
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: workflow-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: PathPrefix
value: /anything/
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: workflow-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: workflow-route
spec:
ingressClassName: apisix
http:
- name: workflow-route
match:
paths:
- /anything/*
upstreams:
- name: httpbin-external-domain
plugins:
- name: workflow
enable: true
config:
rules:
- case:
- ["uri", "==", "/anything/rejected"]
actions:
- - return
- code: 403
将配置应用到集群:
kubectl apply -f workflow-ic.yaml
❶ 仅当请求的 URI 路径为 /anything/rejected 时触发动作。
❷ 当规则匹配时,返回 HTTP 状态码 403。
发送一个不匹配任何规则的请求:
curl -i "http://127.0.0.1:9080/anything/anything"
你应该会收到 HTTP/1.1 200 OK 响应。
发送一个匹配已配置规则的请求:
curl -i "http://127.0.0.1:9080/anything/rejected"
你应该会收到如下内容的 HTTP/1.1 403 Forbidden 响应:
{"error_msg":"rejected by workflow"}
根据 URI 和查询参数条件式应用限流
以下示例演示了一个具有两个匹配条件和一个关联操作的规则,用于按条件对请求进行限流。
创建一个启用 workflow 插件的路由:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "workflow-route",
"uri": "/anything/*",
"plugins":{
"workflow":{
"rules":[
{
"case":[
["uri", "==", "/anything/rate-limit"],
["arg_env", "==", "v1"]
],
"actions":[
[
"limit-count",
{
"count":1,
"time_window":60,
"rejected_code":429
}
]
]
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /anything/*
name: workflow-route
plugins:
workflow:
rules:
- case:
- ["uri", "==", "/anything/rate-limit"]
- ["arg_env", "==", "v1"]
actions:
- - limit-count
- count: 1
time_window: 60
rejected_code: 429
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: workflow-plugin-config
spec:
plugins:
- name: workflow
config:
rules:
- case:
- ["uri", "==", "/anything/rate-limit"]
- ["arg_env", "==", "v1"]
actions:
- - limit-count
- count: 1
time_window: 60
rejected_code: 429
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: workflow-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: PathPrefix
value: /anything/
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: workflow-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: workflow-route
spec:
ingressClassName: apisix
http:
- name: workflow-route
match:
paths:
- /anything/*
upstreams:
- name: httpbin-external-domain
plugins:
- name: workflow
enable: true
config:
rules:
- case:
- ["uri", "==", "/anything/rate-limit"]
- ["arg_env", "==", "v1"]
actions:
- - limit-count
- count: 1
time_window: 60
rejected_code: 429
将配置应用到集群:
kubectl apply -f workflow-ic.yaml
❶ 匹配 URI 路径 /anything/rate-limit。
❷ 匹配值为 v1 的查询参数 env。有关可用于构建条件的更多变量,请参阅内置变量。
❸ 当两个条件都匹配时应用限流。
连续发送两个匹配第二条规则的请求:
curl -i "http://127.0.0.1:9080/anything/rate-limit?env=v1"
你应该会收到一个 HTTP/1.1 200 OK 响应和一个 HTTP 429 Too Many Requests 响应。
发送不匹配该条件的请求:
curl -i "http://127.0.0.1:9080/anything/anything?env=v1"
由于这些请求未被限流,你应该会收到所有请求的 HTTP/1.1 200 OK 响应。
根据消费者条件式应用限流
以下示例演示如何配置插件以根据以下规格执行限流:
- 消费者
john应在 30 秒时间窗口内拥有 5 个请求的配额。 - 消费者
jane应在 30 秒时间窗口内拥有 3 个请求的配额。 - 所有其他消费者应在 30 秒时间窗口内拥有 2 个请求的配额。
虽然此示例将使用 key-auth,但你可以轻松地将其替换为其他身份验证插件。
- Admin API
- ADC
- Ingress Controller
创建消费者 john:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "john"
}'
为该消费者创建 key-auth 凭证:
curl "http://127.0.0.1:9180/apisix/admin/consumers/john/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'
创建第二个消费者 jane:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "jane"
}'
为该消费者创建 key-auth 凭证:
curl "http://127.0.0.1:9180/apisix/admin/consumers/jane/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-jane-key-auth",
"plugins": {
"key-auth": {
"key": "jane-key"
}
}
}'
创建第三个消费者 jimmy:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "jimmy"
}'
为该消费者创建 key-auth 凭证:
curl "http://127.0.0.1:9180/apisix/admin/consumers/jimmy/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-jimmy-key-auth",
"plugins": {
"key-auth": {
"key": "jimmy-key"
}
}
}'
创建一个启用 workflow 插件的路由:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "workflow-route",
"uri": "/anything",
"plugins":{
"key-auth": {},
"workflow":{
"rules":[
{
"actions": [
[
"limit-count",
{
"count": 5,
"key": "consumer_john",
"key_type": "constant",
"rejected_code": 429,
"time_window": 30,
"policy": "local"
}
]
],
"case": [
[
"consumer_name",
"==",
"john"
]
]
},
{
"actions": [
[
"limit-count",
{
"count": 3,
"key": "consumer_jane",
"key_type": "constant",
"rejected_code": 429,
"time_window": 30,
"policy": "local"
}
]
],
"case": [
[
"consumer_name",
"==",
"jane"
]
]
},
{
"actions": [
[
"limit-count",
{
"count": 2,
"key": "$consumer_name",
"key_type": "var",
"rejected_code": 429,
"time_window": 30,
"policy": "local"
}
]
]
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'
创建三个消费者和一个按消费者启用限速的路由:
consumers:
- username: john
credentials:
- name: key-auth
type: key-auth
config:
key: john-key
- username: jane
credentials:
- name: key-auth
type: key-auth
config:
key: jane-key
- username: jimmy
credentials:
- name: key-auth
type: key-auth
config:
key: jimmy-key
services:
- name: httpbin
routes:
- uris:
- /anything
name: workflow-route
plugins:
key-auth: {}
workflow:
rules:
- case:
- ["consumer_name", "==", "john"]
actions:
- - limit-count
- count: 5
key: consumer_john
key_type: constant
rejected_code: 429
time_window: 30
policy: local
- case:
- ["consumer_name", "==", "jane"]
actions:
- - limit-count
- count: 3
key: consumer_jane
key_type: constant
rejected_code: 429
time_window: 30
policy: local
- actions:
- - limit-count
- count: 2
key: "$consumer_name"
key_type: var
rejected_code: 429
time_window: 30
policy: local
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
将配置同步到网关:
adc sync -f adc.yaml
创建三个消费者和一个按消费者启用限速的路由:
使用 Ingress Controller 配置消费者时,消费者名称会按 namespace_consumername 格式生成。因此,workflow 插件中的 consumer_name 逻辑应匹配此格式的消费者名称。
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: john
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: primary-key
config:
key: john-key
---
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: jane
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: primary-key
config:
key: jane-key
---
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: jimmy
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: primary-key
config:
key: jimmy-key
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: workflow-plugin-config
spec:
plugins:
- name: key-auth
config:
_meta:
disable: false
- name: workflow
config:
rules:
- case:
- ["consumer_name", "==", "aic_john"]
actions:
- - limit-count
- count: 5
key: consumer_john
key_type: constant
rejected_code: 429
time_window: 30
policy: local
- case:
- ["consumer_name", "==", "aic_jane"]
actions:
- - limit-count
- count: 3
key: consumer_jane
key_type: constant
rejected_code: 429
time_window: 30
policy: local
- actions:
- - limit-count
- count: 2
key: "$consumer_name"
key_type: var
rejected_code: 429
time_window: 30
policy: local
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: workflow-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: workflow-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: john
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: john-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: jane
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: jane-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: jimmy
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: jimmy-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: workflow-route
spec:
ingressClassName: apisix
http:
- name: workflow-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: key-auth
enable: true
- name: workflow
enable: true
config:
rules:
- case:
- ["consumer_name", "==", "aic_john"]
actions:
- - limit-count
- count: 5
key: consumer_john
key_type: constant
rejected_code: 429
time_window: 30
policy: local
- case:
- ["consumer_name", "==", "aic_jane"]
actions:
- - limit-count
- count: 3
key: consumer_jane
key_type: constant
rejected_code: 429
time_window: 30
policy: local
- actions:
- - limit-count
- count: 2
key: "$consumer_name"
key_type: var
rejected_code: 429
time_window: 30
policy: local
将配置应用到集群:
kubectl apply -f workflow-ic.yaml
❶ 在路由上启用 key-auth。
❷ 匹配消费者 john 并应用 30 秒时间窗口内 5 个请求的限流配额。
❸ 匹配消费者 jane 并应用 30 秒时间窗口内 3 个请求的限流配额。
❹ 匹配所有其他消费者,并为每个消费者应用 30 秒时间窗口内 2 个请求的限流配额。
要验证,请使用 john 的密钥连续发送 6 个请求:
resp=$(seq 6 | xargs -I{} curl "http://127.0.0.1:9080/anything" -H 'apikey: john-key' -o /dev/null -s -w "%{http_code}\n") && \
count_200=$(echo "$resp" | grep "200" | wc -l) && \
count_429=$(echo "$resp" | grep "429" | wc -l) && \
echo "200": $count_200, "429": $count_429
你应该看到以下响应,显示在 6 个请求中,5 个请求成功(状态码 200),而其余请求被拒绝(状态码 429)。
200: 5, 429: 1
使用 jane 的密钥连续发送 6 个请求:
resp=$(seq 6 | xargs -I{} curl "http://127.0.0.1:9080/anything" -H 'apikey: jane-key' -o /dev/null -s -w "%{http_code}\n") && \
count_200=$(echo "$resp" | grep "200" | wc -l) && \
count_429=$(echo "$resp" | grep "429" | wc -l) && \
echo "200": $count_200, "429": $count_429
你应该看到以下响应,显示在 6 个请求中,3 个请求成功(状态码 200),而其余请求被拒绝(状态码 429)。
200: 3, 429: 3
使用 jimmy 的密钥连续发送 3 个请求:
resp=$(seq 3 | xargs -I{} curl "http://127.0.0.1:9080/anything" -H 'apikey: jimmy-key' -o /dev/null -s -w "%{http_code}\n") && \
count_200=$(echo "$resp" | grep "200" | wc -l) && \
count_429=$(echo "$resp" | grep "429" | wc -l) && \
echo "200": $count_200, "429": $count_429
你应该看到以下响应,显示在 3 个请求中,2 个请求成功(状态码 200),而其余请求被拒绝(状态码 429)。
200: 2, 429: 1
使用滑动窗口应用高级限流
以下示例演示如何配置 workflow 与企业版 limit-count-advanced 插件,以使用滑动窗口算法按条件执行限流。
创建一个启用 workflow 插件的路由:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "workflow-route",
"uri": "/anything/*",
"plugins":{
"workflow":{
"rules":[
{
"case": [
["uri", "==", "/anything/rate-limit-advanced"]
],
"actions": [
[
"limit-count-advanced",
{
"count": 5,
"time_window": 10,
"rejected_code": 429,
"policy": "local",
"key_type": "var",
"key": "remote_addr",
"window_type": "sliding"
}
]
]
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /anything/*
name: workflow-route
plugins:
workflow:
rules:
- case:
- ["uri", "==", "/anything/rate-limit-advanced"]
actions:
- - limit-count-advanced
- count: 5
time_window: 10
rejected_code: 429
policy: local
key_type: var
key: remote_addr
window_type: sliding
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: workflow-plugin-config
spec:
plugins:
- name: workflow
config:
rules:
- case:
- ["uri", "==", "/anything/rate-limit-advanced"]
actions:
- - limit-count-advanced
- count: 5
time_window: 10
rejected_code: 429
policy: local
key_type: var
key: remote_addr
window_type: sliding
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: workflow-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: PathPrefix
value: /anything/
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: workflow-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: workflow-route
spec:
ingressClassName: apisix
http:
- name: workflow-route
match:
paths:
- /anything/*
upstreams:
- name: httpbin-external-domain
plugins:
- name: workflow
enable: true
config:
rules:
- case:
- ["uri", "==", "/anything/rate-limit-advanced"]
actions:
- - limit-count-advanced
- count: 5
time_window: 10
rejected_code: 429
policy: local
key_type: var
key: remote_addr
window_type: sliding
将配置应用到集群:
kubectl apply -f workflow-ic.yaml
❶ 匹配 URI 路径 /anything/rate-limit-advanced。
❷ 条件匹配时应用限流。
❸ 将限流算法设置为滑动窗口。
每隔一秒向匹配该条件的路由生成 7 个请求:
for i in $(seq 7); do
(curl -I "http://127.0.0.1:9080/anything/rate-limit-advanced" &)
sleep 1
done
你应该会收到大多数请求的 HTTP/1.1 200 OK 响应,其余请求为 HTTP 429 Too Many Requests 响应。
如果你向具有其他路径的路由发送请求,例如:
curl -i "http://127.0.0.1:9080/anything/else"
由于条件不匹配,你将不会观察到任何生效的限流。