APISIX 高级路由实战(二):插件扩展、限流与无损发布

来自AI助手的总结
文章介绍了ApisixRoute的多域名路由、插件、认证与访问控制用法。
APISIX 高级路由实战(二):插件扩展、限流与无损发布

一、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

根据 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

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容