Envoy 数据面路由与加权流量切分实战
Envoy 常被当作"Istio 的 sidecar"来认识,但它本体是一个通用 L7 代理:路由、加权分流、重试、熔断、可观测性都在它自己身上。理解 Envoy 的路由模型,比理解任何 Service Mesh 抽象都更底层、更耐用。本文按 Listener、Route、Cluster、Endpoint 四层展开。
一、四层模型与两个关键语义
Listener(监听端口)
→ Filter Chain(HCM 等网络过滤器)
→ RouteConfiguration(虚拟主机与路由规则)
→ Cluster(逻辑服务及其 Endpoint)
两个最容易被忽略的语义:
- Cluster 是逻辑服务定义(LB 策略、熔断、健康检查、连接池),Route 只负责如何选 Cluster(匹配条件加目标);
- 路由匹配是顺序优先:第一条完全匹配即生效,不是"最具体优先"。规则顺序写错,后面的规则永远命中不了。
一个可用的静态骨架:
static_resources:
listeners:
- name: http
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: api
domains: ["api.okgoes.com", "api.okgoes.com:10000"]
routes:
- match: { prefix: "/api/v1/articles" }
route: { cluster: article-svc, timeout: 2s }
- match: { prefix: "/" }
route: { cluster: web-svc, timeout: 5s }
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: article-svc
type: STRICT_DNS
lb_policy: LEAST_REQUEST
load_assignment:
cluster_name: article-svc
endpoints:
- lb_endpoints:
- endpoint: { address: { socket_address: { address: article-svc, port_value: 8080 } } }
stat_prefix 是所有指标名的前缀,一旦上报就别再改,否则看板全断。
二、加权流量切分的四种写法
其一,Endpoint 权重,用于同服务不同版本之间分流:
load_assignment:
cluster_name: article-svc
endpoints:
- lb_endpoints: [{ endpoint: { address: {...v1...} }, weight: 90 }]
- lb_endpoints: [{ endpoint: { address: {...v2...} }, weight: 10 }]
其二,Route 级 weighted_clusters,跨服务 A/B 最直观,还能顺手打实验标:
routes:
- match: { prefix: "/api/v1/search" }
route:
weighted_clusters:
total_weight: 100
clusters:
- name: search-v1
weight: 95
- name: search-v2
weight: 5
request_headers_to_add:
- { header: { key: "x-experiment", value: "search-v2" }, append: false }
其三,Header 定向,让内部账号先体验新版,规则必须放在通用规则之前:
routes:
- match:
prefix: "/api/v1/search"
headers:
- name: x-user-id
string_match: { safe_regex: { regex: "^(10[0-9]{8})$" } }
route: { cluster: search-v2 }
- match: { prefix: "/api/v1/search" }
route: { cluster: search-v1 }
其四,一致性分流。纯随机加权会让同一用户在两个版本之间来回跳,体验割裂。要么用一致性哈希按用户主体分流:
lb_policy: RING_HASH
hash_policy:
- header: { name: "x-user-id" }
要么下发会话标识并由上游保证粘性。做实验分流时,"同一个人始终看到同一个版本"几乎总是必需项。
三、重试与超时:默认值几乎都不对
Envoy 默认路由超时 15 秒、无重试、无熔断。生产最少要设这三样:
routes:
- match: { prefix: "/api/v1/" }
route:
cluster: backend
timeout: 1s
idle_timeout: 3s
retry_policy:
retry_on: 5xx,reset,retriable-status-codes
num_retries: 2
per_try_timeout: 300ms
retry_back_off: { base_interval: 25ms, max_interval: 250ms }
retriable_status_codes: [503]
三个陷阱:
timeout是整条请求上限,per_try_timeout是单次尝试上限。timeout: 1s配per_try_timeout: 800ms再重试 2 次,第二次永远活不过 200ms,重试形同虚设;- 重试只对幂等操作安全,默认
retry_on不含 POST;若要重试非幂等写请求,必须业务侧确认; 5xx与reset类重试会在下游过载时放大流量,形成重试风暴,因此必须与熔断配对。
四、三层保护各司其职
- name: backend
type: STRICT_DNS
connect_timeout: 0.25s
lb_policy: LEAST_REQUEST
circuit_breakers:
thresholds:
- priority: DEFAULT
max_connections: 200
max_pending_requests: 100
max_requests: 400
max_retries: 2
outlier_detection:
consecutive_5xx: 5
interval: 10s
base_ejection_time: 30s
max_ejection_percent: 50
连接池上限保护下游资源,outlier detection 踢掉持续报错的实例,circuit breaker 在本地快速失败。三者职责不同,不是重复配置。max_retries 单独限制重试并发,是防重试风暴最有效的一层。
五、观测重点与诊断字段
envoy_cluster_upstream_cx_active
envoy_cluster_upstream_rq_per_try_timeout
envoy_cluster_upstream_rq_retry / envoy_cluster_upstream_rq_retry_success
envoy_cluster_upstream_cx_pool_overflow
envoy_cluster_upstream_circuit_breakers_default_remaining
三条常用判断:rq_retry / rq_total 偏高说明下游在抖动,先查下游而不是改路由;cx_pool_overflow 增长说明触达连接池上限;rq_per_try_timeout 高说明单次超时设得过小。
访问日志里务必打出 %RESPONSE_FLAGS%,这是 Envoy 独有的诊断字段:UT 上游超时、UF 连接失败、UH 无健康主机、LR 本地限速、DC 下游断连。排查"这个 502 到底是谁的锅"基本就靠它。
六、xDS 与热更新的三条纪律
生产要用动态配置(LDS、RDS、CDS、EDS)而非静态文件,否则会失去健康检查与增量更新能力。三条纪律:
- 不要通过重启 Envoy 来改流量。xDS 推送是原子的,重启会打断长连接;
drain_time要给足,滚动升级时保留旧 listener 一段时间让连接自然结束,否则表现为零星 502;- 配置变更必须灰度。xDS 控制面要有 dry-run 与回滚能力,一份写错的 RDS 能让全站瞬间"无健康主机"。
envoy --mode validate -c /etc/envoy/envoy.yaml # 上线前必做
curl -X POST http://127.0.0.1:9901/reload # 静态配置场景热加载
小结
Envoy 的心智模型是路由决定选哪个集群,集群决定怎么连,再叠上路由匹配的顺序优先语义,就理解了八成配置能力。流量切分按"是否跨服务"在 endpoint weight 与 weighted_clusters 之间选择,并确定一致性分流策略。生产配置最少四件事都要做:路由 timeout 与 per_try_timeout 匹配、重试配熔断、连接池上限与 outlier 一起上、访问日志带 %RESPONSE_FLAGS%。守住这三层保护与一条诊断字段,Envoy 才真正担得起入口职责,而不是一个会转发的黑盒。
评论(0)
登录 后参与评论。