4. 基于Header的流量路由:配置Route匹配规则,实现租户A/B流量分发
在多租户架构中,Envoy 通过 Header 路由 实现租户级别的流量隔离与分发。本节将深入讲解如何基于 HTTP Header 中的租户标识(如 x-tenant-id)配置 Route 匹配规则,将流量精准路由至对应的后端集群,并演示 A/B 租户的流量分发策略。
4.1 核心概念:Header 路由与租户标识
Envoy 的 RouteConfiguration 支持基于 请求 Header 的匹配规则。在多租户场景中,通常由网关或客户端在请求中注入租户标识 Header,Envoy 根据该 Header 的值选择对应的路由集群。
| 概念 | 说明 | 典型 Header 示例 |
|---|---|---|
| 租户标识 Header | 用于区分不同租户的 HTTP Header,通常由上游网关或客户端 SDK 注入 | x-tenant-id: tenant-a |
| Header 匹配规则 | Envoy 在 RouteMatch 中定义的 headers 字段,支持精确匹配、正则匹配、范围匹配等 |
name: x-tenant-idexact_match: "tenant-a" |
| 虚拟主机 (VirtualHost) | 一组路由规则的集合,通常对应一个域名或一组域名 | domains: ["*"] |
| 集群 (Cluster) | 后端服务的端点集合,每个租户可对应独立的集群 | cluster: tenant-a-backend |
最佳实践: 建议使用
x-tenant-id 作为标准租户标识 Header,避免使用 Host 或 Authorization 等标准 Header 承载租户信息,以保持语义清晰且不干扰其他中间件处理。
4.2 配置示例:基于 Header 的租户 A/B 路由
以下是一个完整的 Envoy 静态配置片段,演示如何根据 x-tenant-id 将流量分发到 租户 A 和 租户 B 的后端集群。
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 10000 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: tenant_service
domains: ["*"]
routes:
- match:
prefix: "/"
headers:
- name: x-tenant-id
exact_match: "tenant-a"
route:
cluster: tenant_a_cluster
- match:
prefix: "/"
headers:
- name: x-tenant-id
exact_match: "tenant-b"
route:
cluster: tenant_b_cluster
- match:
prefix: "/"
route:
cluster: default_cluster
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: tenant_a_cluster
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: tenant_a_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: tenant-a-backend, port_value: 8080 }
- name: tenant_b_cluster
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: tenant_b_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: tenant-b-backend, port_value: 8080 }
- name: default_cluster
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: default_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: default-backend, port_value: 8080 }
配置要点解析:
- 路由优先级: Envoy 按配置顺序匹配路由,因此租户 A/B 的精确匹配规则应放在默认路由之前。
- 默认路由: 当请求未携带
x-tenant-id或值不匹配时,流量落入default_cluster,可作为兜底或灰度策略。 - 集群隔离: 每个租户拥有独立的集群,可实现资源隔离与故障域隔离。
4.3 流量分发流程:Header 路由决策图
下图展示了 Envoy 接收到请求后,基于 x-tenant-id Header 进行路由决策的完整流程。
4.4 高级匹配规则:正则与范围匹配
除了精确匹配,Envoy 还支持 正则匹配 和 范围匹配,适用于更复杂的租户标识场景,例如租户 ID 包含版本号或环境标识。
| 匹配类型 | 配置字段 | 示例 | 适用场景 |
|---|---|---|---|
| 精确匹配 | exact_match |
exact_match: "tenant-a" |
租户标识固定不变 |
| 正则匹配 | safe_regex_match |
safe_regex_match: { regex: "tenant-[a-z]+" } |
租户 ID 包含动态后缀(如环境、版本) |
| 范围匹配 | range_match |
range_match: { start: 100, end: 200 } |
租户 ID 为数字范围,用于灰度或分桶 |
| 前缀匹配 | prefix_match |
prefix_match: "tenant-" |
租户标识具有统一前缀 |
| 存在匹配 | present_match |
present_match: true |
仅检查 Header 是否存在,不关心值 |
注意: 正则匹配使用
safe_regex_match 而非 regex_match,以避免 ReDoS 攻击。建议在生产环境中对正则表达式进行性能测试。
4.5 多 Header 组合匹配与权重路由
Envoy 支持在一条路由规则中组合多个 Header 条件,实现更精细的流量控制。同时,结合 权重路由 (Weighted Clusters),可以实现租户内部的 A/B 测试或灰度发布。
routes:
- match:
prefix: "/"
headers:
- name: x-tenant-id
exact_match: "tenant-a"
- name: x-env
exact_match: "staging"
route:
weighted_clusters:
clusters:
- name: tenant_a_v1
weight: 90
- name: tenant_a_v2
weight: 10
组合匹配效果: 只有当请求同时携带
x-tenant-id: tenant-a 和 x-env: staging 时,才会匹配该路由,并将 90% 流量导向 v1 版本,10% 导向 v2 版本。这为多租户场景下的灰度发布提供了灵活的控制能力。
4.6 验证与调试
配置完成后,可通过 curl 命令验证 Header 路由是否生效:
# 请求租户A
curl -H "x-tenant-id: tenant-a" http://localhost:10000/api/v1/resource
# 请求租户B
curl -H "x-tenant-id: tenant-b" http://localhost:10000/api/v1/resource
# 请求默认路由(不携带Header)
curl http://localhost:10000/api/v1/resource
通过 Envoy 的 Admin 接口 查看路由统计和集群状态:
# 查看路由配置
curl http://localhost:9901/config_dump
# 查看集群统计
curl http://localhost:9901/clusters
调试建议: 在开发环境中,可以在 Envoy 配置中开启
access_log,记录每个请求的 Header 信息和路由决策,便于快速定位路由问题。