跳到正文
Træfɪk

多层路由

通过路由器层级关系支持高级路由场景。

概览

多层路由允许在路由器之间建立层级关系, 使父路由器在子路由器做出最终路由决策前,通过中间件处理请求。

此功能允许父级中间件修改请求(添加请求头、执行身份认证等),进而影响子路由器如何判断规则并将流量路由到服务。

多层路由特别适合逐步丰富请求信息:每一层都为请求添加上下文,使路由决策越来越具体:

  • 基于身份认证的路由:父路由器对请求进行身份认证,并将用户上下文(角色、权限)添加为请求头,子路由器根据这些请求头路由
  • 分阶段应用中间件:在父级(针对指定域名/路径)应用通用中间件(限流、CORS),在子级应用特定中间件

提供者支持

以下提供者支持多层路由:

  • 文件提供者(YAML、TOML、JSON)
  • KV 存储(Consul、etcd、Redis、ZooKeeper)
  • Kubernetes CRD(IngressRoute)

其他提供者(Docker、Kubernetes Ingress、Gateway API 等)不支持多层路由。

工作原理

Request → EntryPoint → Parent Router → Middleware → Child Router A → Service A
                                          ↓       → Child Router B → Service B
                                     Modify Request
                                  (e.g., add headers)
  1. 请求到达入口点
  2. 父路由器匹配其规则(例如 Host(`example.com`))
  3. 父级中间件执行,可能修改请求
  4. 一个子路由器匹配其规则(可以使用修改后的请求属性)
  5. 请求转发到匹配的子路由器所引用的服务

构建路由器层级

根路由器

  • 没有 parentRefs(位于层级顶端)
  • 可以配置 tls、observability 和 entryPoints
  • 可以是父路由器(有子级),也可以是独立路由器(有服务)
  • 可以应用模型(非根路由器不能使用模型)

中间路由器

  • 通过 parentRefs 引用父路由器
  • 拥有一个或多个子路由器
  • 不得定义 service
  • 不得配置 entryPoints、tls 或 observability

叶路由器

  • 通过 parentRefs 引用父路由器
  • 必须定义 service
  • 不得配置 entryPoints、tls 或 observability

配置示例

基于身份认证的路由
## Dynamic configuration
http:
  routers:
    # Parent router with authentication
    api-parent:
      rule: "PathPrefix(`/api`)"
      middlewares:
        - auth-middleware
      entryPoints:
        - websecure
      tls: {}
      # Note: No service defined - this is a parent router

    # Child router for admin users
    api-admin:
      rule: "HeaderRegexp(`X-User-Role`, `admin`)"
      service: admin-service
      parentRefs:
        - api-parent

    # Child router for regular users
    api-user:
      rule: "HeaderRegexp(`X-User-Role`, `user`)"
      service: user-service
      parentRefs:
        - api-parent

  middlewares:
    auth-middleware:
      forwardAuth:
        address: "http://auth-service:8080/auth"
        authResponseHeaders:
          - X-User-Role
          - X-User-Name

  services:
    admin-service:
      loadBalancer:
        servers:
          - url: "http://admin-backend:8080"

    user-service:
      loadBalancer:
        servers:
          - url: "http://user-backend:8080"
## Dynamic configuration
[http.routers]
  # Parent router with authentication
  [http.routers.api-parent]
    rule = "PathPrefix(`/api`)"
    middlewares = ["auth-middleware"]
    entryPoints = ["websecure"]
    [http.routers.api-parent.tls]
    # Note: No service defined - this is a parent router

  # Child router for admin users
  [http.routers.api-admin]
    rule = "HeaderRegexp(`X-User-Role`, `admin`)"
    service = "admin-service"
    parentRefs = ["api-parent"]

  # Child router for regular users
  [http.routers.api-user]
    rule = "HeaderRegexp(`X-User-Role`, `user`)"
    service = "user-service"
    parentRefs = ["api-parent"]

[http.middlewares]
  [http.middlewares.auth-middleware.forwardAuth]
    address = "http://auth-service:8080/auth"
    authResponseHeaders = ["X-User-Role", "X-User-Name"]

[http.services]
  [http.services.admin-service.loadBalancer]
    [[http.services.admin-service.loadBalancer.servers]]
      url = "http://admin-backend:8080"

  [http.services.user-service.loadBalancer]
    [[http.services.user-service.loadBalancer.servers]]
      url = "http://user-backend:8080"
| Key                                                                    | Value                           |
|------------------------------------------------------------------------|---------------------------------|
| `traefik/http/routers/api-parent/rule`                                 | `PathPrefix(\`/api\`)`          |
| `traefik/http/routers/api-parent/middlewares/0`                        | `auth-middleware`               |
| `traefik/http/routers/api-parent/entrypoints/0`                        | `websecure`                     |
| `traefik/http/routers/api-parent/tls`                                  | `true`                          |
| `traefik/http/routers/api-admin/rule`                                  | `HeaderRegexp(\`X-User-Role\`, \`admin\`)` |
| `traefik/http/routers/api-admin/service`                               | `admin-service`                 |
| `traefik/http/routers/api-admin/parentrefs/0`                          | `api-parent`                    |
| `traefik/http/routers/api-user/rule`                                   | `HeaderRegexp(\`X-User-Role\`, \`user\`)` |
| `traefik/http/routers/api-user/service`                                | `user-service`                  |
| `traefik/http/routers/api-user/parentrefs/0`                           | `api-parent`                    |
| `traefik/http/middlewares/auth-middleware/forwardauth/address`         | `http://auth-service:8080/auth` |
| `traefik/http/middlewares/auth-middleware/forwardauth/authresponseheaders/0` | `X-User-Role`         |
| `traefik/http/middlewares/auth-middleware/forwardauth/authresponseheaders/1` | `X-User-Name`         |
| `traefik/http/services/admin-service/loadbalancer/servers/0/url`       | `http://admin-backend:8080`     |
| `traefik/http/services/user-service/loadbalancer/servers/0/url`        | `http://user-backend:8080`      |

工作原理:

  1. 发往 /api/endpoint 的请求匹配 api-parent 路由器
  2. auth-middleware(ForwardAuth)验证请求并添加 X-User-Role 请求头
  3. 子路由器对修改后的请求进行判断
  4. 如果为 X-User-Role: admin,则匹配 api-admin 路由器,并转发到 admin-service
  5. 如果为 X-User-Role: user,则匹配 api-user 路由器,并转发到 user-service

在生产环境使用 Traefik OSS?

如果你在工作中使用 Traefik,可以考虑为 Traefik OSS 增加企业级 API 网关能力或商业支持。

为 Traefik OSS 增加 API 网关能力快捷且平滑,无需推倒重来,现有配置也会完整保留。请通过这个简短视频了解实际效果。


版权所有 © 头文件软件工作室

文档由 HeadFile Studio 翻译。

Traefik v3.7 中文快照 · 原文版权归 Traefik Labs 及贡献者所有 · MIT 许可证