条件流量管理
条件流量管理是指根据每个请求的某些特征(例如请求标头、URI 参数或 URI 路径)执行特定操作的能力。这使得人们能够实施动态和灵活的路由、限流限速或其他操作,从而允许根据应用程序或系统的特定需求对网关的行为进行细粒度控制和自定义。
本指南将向你展示如何使用 traffic-split、traffic-label 和 workflow 插件在 APISIX 中有条件地管理流量。
前置条件
按条件和比例转发流量
在本节中,你将了解如何使用 traffic-split 插件按条件和权重将流量转发到不同的上游服务。
创建如下路由:
- 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 '{
"uri": "/headers",
"id": "traffic-split-route",
"plugins": {
"traffic-split": {
"rules": [
{
"match": [
{
// Annotate 1
"vars": [
["arg_name","==","jack"],
["http_user-id",">","23"],
["http_apisix-key","~~","[a-z]+"]
]
}
],
"weighted_upstreams": [
{
"upstream": {
"type": "roundrobin",
"scheme": "https",
"pass_host": "node",
"nodes": {
"httpbin.org:443":1
}
},
"weight": 3
},
{
"weight": 2
}
]
}
]
}
},
"upstream": {
"type": "roundrobin",
"scheme": "https",
"pass_host": "node",
"nodes": {
"mock.api7.ai:443":1
}
}
}'
❶ 仅当请求包含 URL 参数 name=jack、标头 user-id 的值大于 23 且另一个标头 apisix-key 的值由小写英文字母组成时,才执行插件以重定向流量。
services:
- name: Mock Service
routes:
- uris:
- /headers
name: traffic-split-route
plugins:
traffic-split:
rules:
- match:
// Annotate 1
- vars:
- [arg_name, "==", "jack"]
- [http_user-id, ">", "23"]
- [http_apisix-key, "~~", "[a-z]+"]
weighted_upstreams:
- upstream:
type: roundrobin
scheme: https
pass_host: node
nodes:
'httpbin.org:443': 1
weight: 3
- weight: 2
upstream:
type: roundrobin
scheme: https
pass_host: node
nodes:
- host: mock.api7.ai
port: 443
weight: 1
❶ 仅当请求包含 URL 参数 name=jack、标头 user-id 的值大于 23 且另一个标头 apisix-key 的值由小写英文字母组成时,才执行插件以重定向流量。
将配置同步到 APISIX:
adc sync -f adc.yaml
为启用了 traffic-split 的路由创建 Kubernetes 清单文件:
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: ingress-apisix
name: traffic-split-plugin-config
spec:
plugins:
- name: traffic-split
config:
rules:
- match:
// Annotate 1
- vars:
- ["arg_name", "==", "jack"]
- ["http_user-id", ">", "23"]
- ["http_apisix-key", "~~", "[a-z]+"]
weighted_upstreams:
- upstream:
scheme: https
pass_host: node
nodes:
httpbin.org:443: 1
weight: 3
- weight: 2
---
apiVersion: v1
kind: Service
metadata:
namespace: ingress-apisix
name: mockapi7-external-domain
spec:
type: ExternalName
externalName: mock.api7.ai
---
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: ingress-apisix
name: passhost-node
spec:
targetRefs:
- name: mockapi7-external-domain
kind: Service
group: ""
passHost: node
scheme: https
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: ingress-apisix
name: traffic-split-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /headers
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: traffic-split-plugin-config
backendRefs:
- name: mockapi7-external-domain
port: 443
weight: 1
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: ingress-apisix
name: mockapi7-external-domain
spec:
scheme: https
passHost: node
externalNodes:
- type: Domain
name: mock.api7.ai
weight: 1
port: 443
---
apiVersion: apisix.apache.org/v2
kind: ApisixPluginConfig
metadata:
namespace: ingress-apisix
name: traffic-split-plugin-config
spec:
ingressClassName: apisix
plugins:
- name: traffic-split
enable: true
config:
rules:
- match:
// Annotate 1
- vars:
- ["arg_name", "==", "jack"]
- ["http_user-id", ">", "23"]
- ["http_apisix-key", "~~", "[a-z]+"]
weighted_upstreams:
- upstream:
scheme: https
pass_host: node
nodes:
httpbin.org:443: 1
weight: 3
- weight: 2
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: ingress-apisix
name: traffic-split-route
spec:
ingressClassName: apisix
http:
- name: traffic-split-route
match:
paths:
- /headers
plugin_config_name: traffic-split-plugin-config
upstreams:
- name: mockapi7-external-domain
❶ 仅当请求包含 URL 参数 name=jack、标头 user-id 的值大于 23 且另一个标头 apisix-key 的值由小写英文字母组成时,才执行插件以重定向流量。
将配置应用到你的集群:
kubectl apply -f traffic-split.yaml
如果满足条件,60% 的流量应指向 httpbin.org,另外 40% 应指向 mock.api7.ai。如果不满足条件,所有流量应指向 mock.api7.ai。
发送 10 个满足所有条件的连续请求以进行验证:
resp=$(seq 10 | xargs -I{} curl "http://127.0.0.1:9080/headers?name=jack" -H 'user-id: 30' -H 'apisix-key: helloapisix' -sL) && \
count_httpbin=$(echo "$resp" | grep "httpbin.org" | wc -l) && \
count_mockapi7=$(echo "$resp" | grep "mock.api7.ai" | wc -l) && \
echo httpbin.org: $count_httpbin, mock.api7.ai: $count_mockapi7
你应该看到类似以下的响应:
httpbin.org: 6, mock.api7.ai: 4
发送 10 个不满足条件的连续请求以进行验证:
resp=$(seq 10 | xargs -I{} curl "http://127.0.0.1:9080/headers?name=random" -sL) && \
count_httpbin=$(echo "$resp" | grep "httpbin.org" | wc -l) && \
count_mockapi7=$(echo "$resp" | grep "mock.api7.ai" | wc -l) && \
echo httpbin.org: $count_httpbin, mock.api7.ai: $count_mockapi7
你应该看到类似以下的响应:
httpbin.org: 0, mock.api7.ai: 10
traffic-split 插件的一个常见用例是实施发布策略,例如金丝雀发布和蓝绿部署。有关更多插件用法,请参阅 插件文档。
按条件和比例标记流 量标头
在本节中,你将了解如何使用企业版 traffic-label 插件按条件和权重向请求添加标头。
创建如下路由:
- 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": "traffic-label-route",
"uri":"/headers",
"plugins":{
"traffic-label": {
"rules": [
{
"match": [
["uri", "==", "/headers"]
],
"actions": [
{
"set_headers": {
"X-Server-Id": 100
},
// Annotate 1
"weight": 3
},
{
"set_headers": {
"X-API-Version": "v2"
},
// Annotate 2
"weight": 2
},
{
// Annotate 3
"weight": 5
}
]
}
]
}
},
"upstream":{
"type":"roundrobin",
"nodes":{
"httpbin.org:80":1
}
}
}'
❶ 30% 的请求应具有 X-Server-Id: 100 请求头。
❷ 20% 的请求应具有 X-API-Version: v2 请求头。
❸ 50% 的请求不应对其执行任何操作。
services:
- name: httpbin Service
routes:
- uris:
- /headers
name: traffic-label-route
plugins:
traffic-label:
rules:
- match:
- [uri, "==", "/headers"]
actions:
- set_headers:
X-Server-Id: 100
// Annotate 1
weight: 3
- set_headers:
X-API-Version: v2
// Annotate 2
weight: 2
// Annotate 3
- weight: 5
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
❶ 30% 的请求应具有 X-Server-Id: 100 请求头。
❷ 20% 的请求应具有 X-API-Version: v2 请求头。
❸ 50% 的请求不应对其执行任何操作。
将配置同步到 APISIX:
adc sync -f adc.yaml
为启用了 traffic-label 的路由创建 Kubernetes 清单文件:
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: ingress-apisix
name: traffic-label-plugin-config
spec:
plugins:
- name: traffic-label
config:
rules:
- match:
- [uri, "==", "/headers"]
actions:
- set_headers:
X-Server-Id: 100
// Annotate 1
weight: 3
- set_headers:
X-API-Version: v2
// Annotate 2
weight: 2
// Annotate 3
- weight: 5
---
apiVersion: v1
kind: Service
metadata:
namespace: ingress-apisix
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: ingress-apisix
name: traffic-label-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /headers
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: traffic-label-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
weight: 1
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: ingress-apisix
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixPluginConfig
metadata:
namespace: ingress-apisix
name: traffic-label-plugin-config
spec:
ingressClassName: apisix
plugins:
- name: traffic-label
enable: true
config:
rules:
- match:
- [uri, "==", "/headers"]
actions:
- set_headers:
X-Server-Id: 100
// Annotate 1
weight: 3
- set_headers:
X-API-Version: v2
// Annotate 2
weight: 2
// Annotate 3
- weight: 5
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: ingress-apisix
name: traffic-label-route
spec:
ingressClassName: apisix
http:
- name: traffic-label-route
match:
paths:
- /headers
plugin_config_name: traffic-label-plugin-config
upstreams:
- name: httpbin-external-domain
❶ 30% 的请求应具有 X-Server-Id: 100 请求头。
❷ 20% 的请求应具有 X-API-Version: v2 请求头。
❸ 50% 的请求不应对其执行任何操作。
将配置应用到你的集群:
kubectl apply -f traffic-label.yaml
生成 50 个连续请求以验证加权操作:
resp=$(seq 50 | xargs -I{} curl "http://127.0.0.1:9080/headers" -sL) && \
count_w3=$(echo "$resp" | grep "X-Server-Id" | wc -l) && \
count_w2=$(echo "$resp" | grep "X-API-Version" | wc -l) && \
echo X-Server-Id: $count_w3, X-API-Version: $count_w2
响应显示标头以加权方式添加到请求中:
X-Server-Id: 15, X-API-Version: 10
有关更多插件用法,请参阅 插件文档。
有条件地对流量进行限流限速
在本节中,你将了解如何使用 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":[
// Annotate 1
["uri", "==", "/anything/rate-limit"],
["arg_env", "==", "v1"]
],
"actions":[
[
// Annotate 2
"limit-count",
{
"count":1,
"time_window":60,
"rejected_code":429
}
]
]
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'
❶ 仅当请求的 URI 路径为 /anything/rate-limit 且包含 URL 参数 env=v1 时,才执行插件以进行限流限速。
❷ 匹配规则时应用限流限速。
services:
- name: httpbin Service
routes:
- uris:
- /anything/*
name: workflow-route
plugins:
workflow:
rules:
- case:
// Annotate 1
- [uri, "==", "/anything/rate-limit"]
- [arg_env, "==", "v1"]
actions:
// Annotate 2
- - limit-count
- count: 1
time_window: 60
rejected_code: 429
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
❶ 仅当请求的 URI 路径为 /anything/rate-limit 且包含 URL 参数 env=v1 时,才执行插件以进行限流限速。
❷ 匹配规则时应用限流限速。
将配置同步到 APISIX:
adc sync -f adc.yaml
为启用了 workflow 的路由创建 Kubernetes 清单文件:
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: ingress-apisix
name: workflow-plugin-config
spec:
plugins:
- name: workflow
config:
rules:
- case:
// Annotate 1
- [uri, "==", "/anything/rate-limit"]
- [arg_env, "==", "v1"]
actions:
// Annotate 2
- - limit-count
- count: 1
time_window: 60
rejected_code: 429
---
apiVersion: v1
kind: Service
metadata:
namespace: ingress-apisix
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: ingress-apisix
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
weight: 1
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: ingress-apisix
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixPluginConfig
metadata:
namespace: ingress-apisix
name: workflow-plugin-config
spec:
ingressClassName: apisix
plugins:
- name: workflow
enable: true
config:
rules:
- case:
// Annotate 1
- [uri, "==", "/anything/rate-limit"]
- [arg_env, "==", "v1"]
actions:
// Annotate 2
- - limit-count
- count: 1
time_window: 60
rejected_code: 429
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: ingress-apisix
name: workflow-route
spec:
ingressClassName: apisix
http:
- name: workflow-route
match:
paths:
- /anything/*
plugin_config_name: workflow-plugin-config
upstreams:
- name: httpbin-external-domain
❶ 仅当请求的 URI 路径为 /anything/rate-limit 且包含 URL 参数 env=v1 时,才执行插件以进行限流限速。
❷ 匹配规则时应用限流限速。
将配置应用到你的集群:
kubectl apply -f workflow.yaml
生成两个符合条件的连续请求:
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 响应,因为它们没有被限流限速。
有关更多插件用法,请参阅 插件文档。
下一步
你现 在已经了解了 APISIX 支持条件流量管理的各种方式,使用 traffic-split、traffic-label 和 workflow 插件。