Envoy 反向代理与流量分割实战

知识库
知识库文档
/tech-stacks/envoy/examples/Envoy 反向代理与流量分割实战.md

文档

目标

用 Envoy 搭建反向代理,实现流量分割(金丝雀发布):90% 流量到 v1,10% 到 v2。演示 L7 路由、加权分流的完整配置。

完整代码

架构

Browser → Envoy(:10000) ──90%──→ backend-v1(:8081)
                         ──10%──→ backend-v2(:8082)

1. 后端服务 v1(Python)

# backend_v1.py
from http.server import HTTPServer, BaseHTTPRequestHandler
import os

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(b'{"version":"v1","message":"This is stable version"}')

HTTPServer(("0.0.0.0", 8081), Handler).serve_forever()

2. 后端服务 v2(Python)

# backend_v2.py
from http.server import HTTPServer, BaseHTTPRequestHandler

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(b'{"version":"v2","message":"This is canary version"}')

HTTPServer(("0.0.0.0", 8082), Handler).serve_forever()

3. Envoy 配置(envoy-canary.yaml)

static_resources:
  listeners:
    - name: main_listener
      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
                route_config:
                  name: canary_routes
                  virtual_hosts:
                    - name: app
                      domains: ["*"]
                      routes:
                        # 精确匹配:/health 走 v1
                        - match: { path: "/health" }
                          route:
                            cluster: backend_v1
                        # 前缀匹配 + 超时配置
                        - match: { prefix: "/" }
                          route:
                            weighted_clusters:
                              clusters:
                                - name: backend_v1
                                  weight: 90
                                - name: backend_v2
                                  weight: 10
                              total_weight: 100
                          retry_policy:
                            retry_on: "5xx"
                            num_retries: 2
                            per_try_timeout: 1s
                http_filters:
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
    - name: backend_v1
      type: STRICT_DNS
      connect_timeout: 2s
      load_assignment:
        cluster_name: backend_v1
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address: { address: 127.0.0.1, port_value: 8081 }
      # 异常检测(熔断)
      circuit_breakers:
        thresholds:
          - priority: DEFAULT
            max_connections: 100
            max_pending_requests: 100
            max_requests: 100
            max_retries: 10
      health_checks:
        - timeout: 1s
          interval: 5s
          unhealthy_threshold: 3
          healthy_threshold: 1
          http_health_check:
            path: "/health"

    - name: backend_v2
      type: STRICT_DNS
      connect_timeout: 2s
      load_assignment:
        cluster_name: backend_v2
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address: { address: 127.0.0.1, port_value: 8082 }
      circuit_breakers:
        thresholds:
          - priority: DEFAULT
            max_connections: 100
            max_pending_requests: 100
            max_requests: 100
            max_retries: 10

4. 管理接口配置

# admin 接口(添加到 envoy-canary.yaml 顶层)
admin:
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

运行步骤

# 1. 启动后端服务
python backend_v1.py &;
python backend_v2.py &;

# 2. 启动 Envoy
envoy -c envoy-canary.yaml

# 3. 验证流量分割
for i in {1..20}; do curl -s http://localhost:10000/api; done | sort | uniq -c
# 预期: 约 18 次 v1, 2 次 v2

# 4. 查看 Envoy 管理接口
curl http://localhost:9901/stats | grep cluster.backend_v1
curl http://localhost:9901/clusters
curl http://localhost:9901/config_dump

# 5. 健康检查
curl http://localhost:10000/health

预期输出

$ for i in {1..20}; do curl -s http://localhost:10000/api; done | sort | uniq -c
     18 {"version":"v1","message":"This is stable version"}
      2 {"version":"v2","message":"This is canary version"}

# 管理接口
$ curl http://localhost:9901/clusters
# backend_v1::observability_name::backend_v1
# backend_v2::observability_name::backend_v2

关键点

  • weighted_clusters 实现加权流量分割,零代码金丝雀发布
  • retry_policy 配置自动重试,retry_on: 5xx 只在服务端错误时重试
  • circuit_breakers 防止连接池耗尽
  • health_checks 自动剔除不健康实例
  • Admin 接口提供运行时诊断能力

信息

路径
/tech-stacks/envoy/examples/Envoy 反向代理与流量分割实战.md
更新时间
2026/5/31