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