一、ApisixRoute 更多进阶用法¶
官方数据:https://apisix.apache.org/zh/docs/apisix/plugins/batch-requests/
1.1 统一入口与路由策略¶
将多个域名绑定到同一个Ingress,意味着这些域名共享相同的入口控制器和路由规则。
确保不同域名下的服务遵循一致的入口流量处理逻辑,如SSL/TLS 、认证、限速、重写、路径映射等, 有利于实现整体服务架构的标准化和规范化。
[root@master01 16]# vim httpbin-test1.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: http-route1
spec:
http:
- name: http-route1
match:
hosts:
- local.example.com
- httpbin.example.com
paths:
- /*
- /api
backends:
- serviceName: httpbin
servicePort: 80
# 应用
[root@master01 16]# kaf httpbin-test1.yaml
# 查看
[root@master01 16]# kg ar | grep http-route1
http-route1 ["local.example.com","httpbin.example.com"] ["/*","/api"] 64s
# 验证
[root@master01 16]# curl -I local.example.com
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Date: Sun, 20 Apr 2025 10:37:56 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
[root@master01 16]# curl -I httpbin.example.com
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Date: Sun, 20 Apr 2025 10:38:19 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
# 环境复原
[root@master01 16]# k delete -f httpbin-test1.yaml
1.2 ApisixRoute添加插件¶
[root@master01 16]# vim httpbin-test2.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: http-route2
spec:
http:
- name: http-route2
match:
hosts:
- httpbin.example.com
paths:
- /*
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: gzip
enable: true
# 应用
[root@master01 16]# kaf httpbin-test2.yaml
# 查看
[root@master01 16]# kg ar | grep http-route2
http-route2 ["httpbin.example.com"] ["/*"] 25s
# 验证
[root@master01 16]# curl -I httpbin.example.com
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Date: Sun, 20 Apr 2025 10:41:01 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
测试验证:
[root@master01 16]# curl -I http://httpbin.example.com -H "Accept-Encoding: gzip"
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Date: Sun, 20 Apr 2025 10:45:07 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
Content-Encoding: gzip
环境复原
[root@master01 16]# k delete -f httpbin-test2.yaml
1.3 基于 apikey 的认证¶
key-auth 插件需要与 Consumer 一起使用才能实现该功能。 开启认证的 apisixroute 会自动匹配key
[root@master01 16]# vim httpbin-test3.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
name: httpserver-basicauth
spec:
authParameter:
keyAuth:
value:
key: <apikey-value>
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: http-route3
spec:
http:
- name: http-route3
match:
hosts:
- httpbin.example.com
paths:
- /*
backends:
- serviceName: httpbin
servicePort: 80
authentication:
enable: true
type: keyAuth
# 应用
[root@master01 16]# kaf httpbin-test3.yaml
测试验证:
#未加apikey
[root@master01 16]# curl httpbin.example.com
{"message":"Missing API key found in request"}
[root@master01 16]# curl -I httpbin.example.com
HTTP/1.1 401 Unauthorized
Date: Sun, 20 Apr 2025 10:50:19 GMT
Content-Type: text/plain; charset=utf-8
Connection: keep-alive
Server: APISIX/3.8.0
#添加apikey
[root@master01 16]# curl -I -H 'apikey:<apikey-value>' httpbin.example.com
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Date: Sun, 20 Apr 2025 10:49:53 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
环境复原
[root@master01 16]# k delete -f httpbin-test3.yaml
1.4 uri-blocker¶
uri-blocker 插件通过指定一系列 block_rules 来拦截用户请求。
场景:
- 阻止常见的恶意扫描、攻击性URI,如尝试探测敏感文件(如 .git 、 .env 、 wp-config.php等)、SQL注入、跨站脚本(XSS)攻击等。
[root@master01 16]# vim httpbin-test4.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: http-route4
spec:
http:
- name: http-route4
match:
hosts:
- httpbin.example.com
paths:
- /*
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: uri-blocker
enable: true
config:
block_rules: ["root.exe", "root.m+", "admin.php"]
# 应用
[root@master01 16]# kaf httpbin-test4.yaml
# 验证
[root@master01 16]# kg -f httpbin-test4.yaml
NAME HOSTS URIS AGE
http-route4 ["httpbin.example.com"] ["/*"] 7s
测试验证:
# 访问正常路由
[root@master01 16]# curl httpbin.example.com -I
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Date: Sun, 20 Apr 2025 11:01:28 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
# 访问被限制的路由
[root@master01 16]# curl httpbin.example.com/admin.php -I
HTTP/1.1 403 Forbidden
Date: Sun, 20 Apr 2025 11:01:55 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 225
Connection: keep-alive
Server: APISIX/3.8.0
环境复原
[root@master01 16]# k delete -f httpbin-test4.yaml
1.5 referer-restriction¶
referer-restriction 插件允许用户将 Referer 请求头中的域名列入白名单或黑名单来限制该域名对服务或路由的访问。
场景:
- 在与合作伙伴进行API集成或内容共享时,可以通过 referer-restriction 设置白名单,仅允许特定合作伙伴的域名发起请求。
[root@master01 16]# vim httpbin-test5.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: http-route5
spec:
http:
- name: http-route5
match:
hosts:
- httpbin.example.com
paths:
- /*
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: referer-restriction
enable: true
config:
bypass_missing: true
whitelist: ["*.jd.com", "baidu.com"]
# 应用
[root@master01 16]# kaf httpbin-test5.yaml
# 验证
[root@master01 16]# kg -f httpbin-test5.yaml
NAME HOSTS URIS AGE
http-route5 ["httpbin.example.com"] ["/*"] 6s
测试验证:
#因为启用插件时会将属性bypass_missing设置为true,所以未指定Refer请求头的请求将跳过检查:
[root@master01 16]# curl httpbin.example.com -I
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Date: Sun, 20 Apr 2025 11:04:31 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
#携带正常的Refer
[root@master01 16]# curl httpbin.example.com -H 'Referer: http://aaa.jd.com/x' -I
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Date: Sun, 20 Apr 2025 11:04:55 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
#携带非正常的Refer
[root@master01 16]# curl httpbin.example.com -H 'Referer: http://spider.ahh.com/x' -I
HTTP/1.1 403 Forbidden
Date: Sun, 20 Apr 2025 11:05:14 GMT
Content-Type: text/plain; charset=utf-8
Connection: keep-alive
Server: APISIX/3.8.0
#携带正常的Refer
[root@master01 16]# curl httpbin.example.com -H 'Referer: http://baidu.com/x' -I
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Date: Sun, 20 Apr 2025 11:05:44 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
#携带非正常的Refer
[root@master01 16]# curl httpbin.example.com -H 'Referer: http://www.baidu.com/x' -I
HTTP/1.1 403 Forbidden
Date: Sun, 20 Apr 2025 11:06:03 GMT
Content-Type: text/plain; charset=utf-8
Connection: keep-alive
Server: APISIX/3.8.0
环境复原
[root@master01 16]# k delete -f httpbin-test5.yaml
1.6 limit-req¶
limit-req 插件使用 漏桶算法限制单个客户端对服务的请求速率,以保护系统免受过载、DDoS攻击或 其他突发流量冲击的影响。
场景:
- 在与合作伙伴进行API集成或内容共享时,限定访问速率,以防止接口挂载导致异常。
官方数据:https://apisix.apache.org/zh/docs/apisix/plugins/limit-req/#
| 名称 | 类型 | 必 选 项 | 默 认 值 | 有效值 | 描述 |
| -------- | -------- | ------------ | ------------ | ---------- | ------------------------------------------------------------ |
| rate | integer | 是 | | rate > 0 | 指定的请求速率(以秒为单位),请求速率超 过 rate 但没有超过( rate + burst )的请求会被延时处理。 |
| burst | integer | 是 | | burst >= 0 | rate + burst )的请求会被请求速率超过( 直接拒绝。 |
[root@master01 16]# vim httpbin-test6.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: http-route6
spec:
http:
- name: http-route6
match:
hosts:
- httpbin.example.com
paths:
- /*
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: limit-req
enable: true
config: {"rate": 1, "burst": 1, "rejected_code": 503, "key_type": "var", "key": "remote_addr"}
# 应用
[root@master01 16]# kaf httpbin-test6.yaml
# 验证
[root@master01 16]# kg -f httpbin-test6.yaml
NAME HOSTS URIS AGE
http-route6 ["httpbin.example.com"] ["/*"] 26s
APISIX 将客户端的 IP 地址作为限制请求速率的条件,当请求速率小于 1 次每秒( rate )时,请求正 常;
当请求速率大于 1 次每秒( rate ),小于 3 次每秒( rate + burst )时,将会对超出部分的请求进行 延迟处理;
当请求速率大于 3 次每秒( rate + burst )时,超出规定数量的请求将返回 HTTP 状态码 503 。
访问验证:
# 并发10个请求
[root@master01 16]# while true; do seq 10 | xargs -P 10 -I{} bash -c 'curl -I httpbin.example.com'; done
...
...
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Date: Sun, 20 Apr 2025 11:09:52 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Date: Sun, 20 Apr 2025 11:09:52 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.8.0
HTTP/1.1 503 Service Temporarily Unavailable
Date: Sun, 20 Apr 2025 11:09:53 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 269
Connection: keep-alive
Server: APISIX/3.8.0
HTTP/1.1 503 Service Temporarily Unavailable
Date: Sun, 20 Apr 2025 11:09:53 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 269
Connection: keep-alive
Server: APISIX/3.8.0
...
...
环境复原:
[root@master01 16]# k delete -f httpbin-test6.yaml
二、基于APISIX网关的无损发布¶
2.1 应用版本部署¶
stable版本:
[root@master01 16]# vim s1-stable.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-stable-service
namespace: default
spec:
ports:
- port: 80
targetPort: 80
name: http-port
selector:
app: myapp
version: stable
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-stable
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: myapp
version: stable
template:
metadata:
labels:
app: myapp
version: stable
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/zhdya/myapp:v1
imagePullPolicy: IfNotPresent
name: myapp-stable
ports:
- name: http-port
containerPort: 80
env:
- name: APP_ENV
value: stable
# 应用
[root@master01 16]# kaf s1-stable.yaml
# 验证
[root@master01 16]# kg -f s1-stable.yaml
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/myapp-stable-service ClusterIP <myapp-stable-service-ip> <none> 80/TCP 21s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/myapp-stable 1/1 1 1 21s
canary版本:
[root@master01 16]# vim s2-canary.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-canary-service
namespace: default
spec:
ports:
- port: 80
targetPort: 80
name: http-port
selector:
app: myapp
version: canary
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-canary
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: myapp
version: canary
template:
metadata:
labels:
app: myapp
version: canary
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/zhdya/myapp:v2
imagePullPolicy: IfNotPresent
name: myapp-canary
ports:
- name: http-port
containerPort: 80
env:
- name: APP_ENV
value: canary
# 应用
[root@master01 16]# kaf s2-canary.yaml
2.2 基于 weight 分流¶
权重是一个非负整数值,表示后端服务在请求分发中的相对重要性或期望接收的请求比例。权重越大,该服务实例被选中的概率越高。
[root@master01 16]# vim s3-apisixroute-weight.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: myapp-canary-apisixroute
namespace: default
spec:
http:
- name: myapp-canary-rule
match:
hosts:
- myapp.example.com
paths:
- /
backends:
- serviceName: myapp-stable-service
servicePort: 80
weight: 70
- serviceName: myapp-canary-service
servicePort: 80
weight: 30
# 应用
[root@master01 16]# kaf s3-apisixroute-weight.yaml
# 验证
[root@master01 16]# kg -f s3-apisixroute-weight.yaml
NAME HOSTS URIS AGE
myapp-canary-apisixroute ["myapp.example.com"] ["/"] 28s
Stable 和 Canary 的比例约为 7:3
[root@master01 16]#
for i in `seq 30`; do curl http://myapp.example.com; done
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v1
myapp:v2
myapp:v1
myapp:v2
myapp:v1
myapp:v2
myapp:v1
myapp:v2
myapp:v1
myapp:v1
环境复原
[root@master01 16]# k delete -f s3-apisixroute-weight.yaml
2.3 基于优先级分流¶
优先级是一个整数值,用于表示路由规则的重要程度或优先处理的顺序。在 APISIX 中,优先级值越大,路由的优先级越高。
[root@master01 16]# vim s4-priority.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: myapp-canary-apisixroute2
namespace: default
spec:
http:
- name: myapp-stable-rule2
priority: 1
match:
hosts:
- myapp.example.com
paths:
- /
backends:
- serviceName: myapp-stable-service
servicePort: 80
- name: myapp-canary-rule2
priority: 2
match:
hosts:
- myapp.example.com
paths:
- /
backends:
- serviceName: myapp-canary-service
servicePort: 80
# 应用
[root@master01 16]# kaf s4-priority.yaml
测试,流量会优先打入优先级高的pod
[root@master01 16]# for i in `seq 30`;do curl http://myapp.example.com;done
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
myapp:v2
环境复原
[root@master01 16]# k delete -f s4-priority.yaml
2.4 基于 header 分流¶
根据 HTTP 请求头(Header)中的特定字段及其值来决定请求应该被路由到哪个后端服务。
[root@master01 16]# vim canary-header.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: myapp-canary-apisixroute3
namespace: default
spec:
http:
- name: myapp-stable-rule3
priority: 1
match:
hosts:
- myapp.example.com
paths:
- /
backends:
- serviceName: myapp-stable-service
servicePort: 80
- name: myapp-canary-rule3
priority: 2
match:
hosts:
- myapp.example.com
paths:
- /
exprs:
- subject:
scope: Header
name: canary
op: RegexMatch
value: ".*myapp.*"
backends:
- serviceName: myapp-canary-service
servicePort: 80
# 应用
[root@master01 16]# kaf canary-header.yaml
测试验证:
[root@master01 16]# curl http://myapp.example.com
myapp:v1
[root@master01 16]# curl http://myapp.example.com -X GET -H "canary: 124myapp"
myapp:v2
[root@master01 16]# curl http://myapp.example.com -X GET -H "canary: myapp"
myapp:v2
[root@master01 16]# curl http://myapp.example.com -X GET -H "canary: zhdyamyapp"
myapp:v2
[root@master01 16]# curl http://myapp.example.com -X GET -H "stable: zhdyamyapp"
myapp:v1
[root@master01 16]# curl http://myapp.example.com -X GET -H "stable: myapp"
myapp:v1
环境复原
[root@master01 16]# k delete -f canary-header.yaml
2.5 基于参数的分流¶
根据HTTP请求中的查询参数(query parameters)或请求体(request body)中的特定字段及其值来决定请求应被路由到哪个后端服务。
[root@master01 16]# vim vars.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: myapp-canary-apisixroute3
namespace: default
spec:
http:
- name: myapp-stable-rule3
priority: 1
match:
hosts:
- myapp.example.com
paths:
- /
backends:
- serviceName: myapp-stable-service
servicePort: 80
- name: myapp-canary-rule3
priority: 2
match:
hosts:
- myapp.example.com
paths:
- /
exprs:
- subject:
scope: Query
name: id
op: In
set:
- "12"
- "23"
- "45"
- "67"
backends:
- serviceName: myapp-canary-service
servicePort: 80
# 应用
[root@master01 16]# kaf vars.yaml
# 验证
[root@master01 16]# kg -f vars.yaml
NAME HOSTS URIS AGE
myapp-canary-apisixroute3 ["myapp.example.com"] ["/"] 48s
测试验证:
[root@master01 16]# curl http://myapp.example.com
myapp:v1
[root@master01 16]# curl http://myapp.example.com
myapp:v1
[root@master01 16]# curl http://myapp.example.com/\?id\=12
myapp:v2
[root@master01 16]# curl http://myapp.example.com/\?id\=23
myapp:v2
[root@master01 16]# curl http://myapp.example.com/\?id\=45
myapp:v2
[root@master01 16]# curl http://myapp.example.com/\?id\=67
myapp:v2
[root@master01 16]# curl http://myapp.example.com/\?id\=89
myapp:v1
[root@master01 16]# curl http://myapp.example.com/\?id\=143
myapp:v1
环境复原
[root@master01 16]# k delete -f vars.yaml
2.6 基于 cookie 分流¶
根据 HTTP 请求中的 Cookie 字段及其值来决定请求应被路由到哪个后端服务。
[root@master01 16]# vim cookie.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: myapp-canary-apisixroute
namespace: default
spec:
http:
- name: myapp-stable-rule3
priority: 1
match:
hosts:
- myapp.example.com
paths:
- /
backends:
- serviceName: myapp-stable-service
servicePort: 80
- name: myapp-canary-rule3
priority: 2
match:
hosts:
- myapp.example.com
paths:
- /
exprs:
- subject:
scope: Cookie
name: canary_v5
op: Equal
value: "always"
backends:
- serviceName: myapp-canary-service
servicePort: 80
# 应用
[root@master01 16]# kaf cookie.yaml
# 验证
[root@master01 16]# kg -f cookie.yaml
NAME HOSTS URIS AGE
myapp-canary-apisixroute ["myapp.example.com"] ["/"] 5s
测试携带cookie:
[root@master01 16]# curl --cookie "canary_v5=always" "http://myapp.example.com"
myapp:v2
测试不携带cookie:
[root@master01 16]# curl "http://myapp.example.com"
myapp:v1
环境复原
[root@master01 16]# k delete -f cookie.yaml -f s1-stable.yaml -f s2-canary.yaml