HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • 代理技术全栈手册

    • 代理技术全栈手册 - HiHuo
    • 原理篇

      • 第01章 代理是什么:正向 / 反向 / 透明 / 隧道的统一模型
      • 第02章 代理与网络层级:L3 / L4 / L5 / L7 在哪里截断流量
      • 第03章 一个请求穿过代理的一生:连接生命周期全景
    • 协议篇

      • 第04章 HTTP 代理协议:绝对 URI、CONNECT 隧道、转发头与连接池
      • 第05章 HTTPS 与 TLS 代理:终止 / 透传 / MITM / SNI / mTLS
      • 第06章 SOCKS 协议:SOCKS4/4a/5 与 UDP ASSOCIATE 报文级解析
      • 第07章 HTTP/2、gRPC 与 HTTP/3(QUIC) 代理的挑战
      • 第08章 代理自动配置:PAC / WPAD / 系统代理 / NO_PROXY
    • 层级与转发篇

      • 第09章 L4 代理:TCP/UDP 转发与连接级负载均衡
      • 第10章 L7 代理:协议感知与基于内容的路由
      • 第11章 透明代理:iptables REDIRECT/DNAT、TPROXY 与 eBPF 劫持
      • 第12章 数据搬运的艺术:splice / sendfile / 零拷贝 / io_uring
    • 组件横评篇

      • 第13章 Nginx / OpenResty:反向代理、upstream 与 Lua 可编程
      • 第14章 HAProxy:L4/L7、ACL、健康检查与 stick table
      • 第15章 Envoy:xDS 动态配置与 filter chain,为何是云原生数据面
      • 第16章 Traefik / Caddy:自动服务发现与自动 HTTPS
      • 第17章 Squid 与正向/缓存代理:企业出网、缓存与审计
      • 第18章 mitmproxy:抓包、改包、脚本化调试
      • 第19章 内网穿透与隧道:frp / gost / SSH 隧道 / ngrok
      • 第20章 科学上网生态的技术原理(技术中立)
    • 多语言手写篇

      • 第21章 Go:100 行手写 HTTP/CONNECT + SOCKS5 代理
      • 第22章 Rust:基于 tokio 的高性能 TCP 代理
      • 第23章 Python:asyncio 实现,适合调试与脚本
      • 第24章 C:epoll 裸写与零拷贝,及语言选型对比
    • 容器与K8s篇

      • 第25章 Docker 里的代理:HTTP_PROXY、build/pull 与 daemon 配置
      • 第26章 Sidecar 与流量劫持:Istio init-container 的 iptables 原理
      • 第27章 Ingress 与南北流量:Ingress-nginx 与 Gateway API
      • 第28章 Egress 与出网治理:出口网关、registry mirror、审计
      • 第29章 Service Mesh 数据面:Envoy Sidecar 全链路
    • 进阶篇

      • 第30章 可编程代理:Lua / Wasm / eBPF / xDS,代理的"软件定义"
      • 第31章 性能调优:并发模型、连接池、超时与重试、压测
      • 第32章 排错决策树:502 / 504 / 握手失败 / 环路 / 泄漏
      • 第33章 代理安全:开放代理、SSRF、凭证泄漏与攻击面
    • 底层机制篇

      • 第34章 代理的背压与流控:一个代理最难的部分
      • 第35章 socket 与 TCP 状态机:半关闭、超时、连接生命周期
      • 第36章 HTTP/2 帧、流控与 HPACK:h2 代理的内部机制
      • 第37章 负载均衡算法推导与韧性状态机
      • 第38章 Capstone:把玩具代理改造成生产级骨架
    • 综合实战篇

      • 第39章 企业多跳转发链:拓扑、协议矩阵与贯穿性难题
      • 第40章 端到端实战:把 6 类流量全代理通
      • 第41章 更刁钻的流量:gRPC、长轮询、WebRTC、大文件、双向流
      • 第42章 可落地完整参考实现:一套能跑的多协议转发栈
    • 附录

      • 附录 A:代理协议报文速查(HTTP / SOCKS / PAC / PROXY protocol)
      • 附录 B:组件选型决策树
      • 附录 C:抓包与命令速查

第15章 Envoy:xDS 动态配置与 filter chain,为何是云原生数据面

学习目标

  • 掌握 Envoy 的核心模型:Listener → Filter Chain → Route → Cluster → Endpoint
  • 理解 xDS 如何让配置"秒级热推、永不 reload"——这是 Envoy 区别于 Nginx 的根本
  • 搞懂 filter chain 责任链如何插入鉴权、限流、故障注入、Wasm
  • 明白为什么 Istio/Service Mesh 选择 Envoy 作数据面

前置知识

  • 第07章 HTTP2/gRPC 代理、第10章 L7、第11章 Sidecar 劫持
  • 第13章 Nginx(对照:静态 vs 动态配置)、apiGateway · 服务网格

原理

定位:为动态配置而生的数据面

Envoy 由 Lyft 开源,生来就是为云原生设计的代理。它和 Nginx/HAProxy 最根本的不同:

Nginx/HAProxy 的配置是静态文件,改了要 reload;Envoy 的配置可以由控制面通过 API 动态下发,秒级热生效、无需重启。 这一条,决定了它成为 Service Mesh 数据面的标准。

在一个有成千上万微服务、实例不断扩缩容的环境里,"改配置要 reload"是不可接受的——这正是 Envoy 的主场。

核心模型:一个请求在 Envoy 里的旅程

                    Envoy 配置层级
  ┌──────────────────────────────────────────────────────┐
  │ Listener   监听地址:端口(如 0.0.0.0:15001)           │
  │   └─ Filter Chain  网络过滤器链                         │
  │        └─ HTTP Connection Manager(L7 入口)           │
  │             └─ HTTP Filters  http 过滤器链             │
  │                  router / ext_authz / ratelimit / ...  │
  │             └─ Route Config  虚拟主机 + 路由规则        │
  │                  match(域名/路径/头) → Cluster          │
  │ Cluster    后端服务(逻辑名)+ 负载均衡 + 健康检查      │
  │   └─ Endpoints  实际后端实例 IP:Port                    │
  └──────────────────────────────────────────────────────┘

  请求流:Listener 收包 → Filter Chain → HTTP filters 逐个处理
        → Route 匹配选 Cluster → 负载均衡选 Endpoint → 转发

记住这条链:Listener(在哪听)→ Route(怎么选服务)→ Cluster(哪个服务)→ Endpoint(哪个实例)。xDS 的每个 D 就对应其中一层。

filter chain:责任链式可扩展

Envoy 的能力来自过滤器链——请求像流水线一样穿过一串 filter,每个 filter 做一件事:

  • Network filters(L4):tcp_proxy(L4 代理)、http_connection_manager(L7 入口)
  • HTTP filters(L7):router(必备,最后一个)、ext_authz(外部鉴权)、ratelimit(限流)、fault(故障注入)、jwt_authn(JWT 校验)、lua、wasm(第30章)

要加能力,就插一个 filter——这种可组合性是 Envoy 灵活的来源。

xDS:动态配置的发现协议

xDS = "x Discovery Service",是一族让控制面动态下发配置的 gRPC/REST API:

缩写全称下发什么
LDSListener Discovery Service监听器
RDSRoute Discovery Service路由规则
CDSCluster Discovery Service后端集群
EDSEndpoint Discovery Service集群里的实例 IP(扩缩容主要靠它)
SDSSecret Discovery Service证书/密钥(mTLS 用)
ADSAggregated Discovery Service把上面聚合到一条流,保证下发顺序一致
  控制面(Istiod 等)          数据面(Envoy)
        │   gRPC 长连接(ADS)        │
        │ ──── CDS:有这些集群 ────▶│
        │ ──── EDS:集群X有这些IP ─▶│  实例扩容 → 控制面推新 EDS → Envoy 秒级生效
        │ ──── LDS/RDS:路由更新 ──▶│  无需 reload、不断连

EDS 的价值:Pod 扩缩容时,控制面只需推一条 EDS 更新,Envoy 立即知道新实例——这在 Nginx 里得改 upstream + reload。

静态配置 vs 动态 xDS

Envoy 既能用静态 YAML(学习/简单场景),也能全动态(生产/Mesh):

  • 静态:所有 Listener/Cluster 写死在 bootstrap 配置里(下面实验一)
  • 动态:bootstrap 里只配"去哪找控制面",其余全走 xDS(Istio 模式)

为什么 Service Mesh 选 Envoy

需求Envoy 的答案
配置秒级热推、海量实例xDS 动态下发,无 reload
gRPC/h2 原生一等公民(第07章)
可观测原生 metrics/access log/分布式追踪
可扩展filter chain + Wasm,不改二进制加能力
mTLSSDS 下发证书,自动双向 TLS(第05章)
平滑升级hot restart(新老进程交接,不丢连接)

这套组合拳让 Istio、Consul、AWS App Mesh、Gateway API 实现纷纷选它作数据面(第29章)。代价是配置复杂、上手陡——直接手写 Envoy YAML 远比 Nginx 繁琐,所以现实中多由控制面生成。


️ 实现 / 命令

实验一:最小静态配置(Listener → Route → Cluster)

# envoy.yaml —— 一个最小 L7 反向代理
static_resources:
  listeners:
  - name: main
    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:
            virtual_hosts:
            - name: backend
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route: { cluster: service_backend }
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
  - name: service_backend
    type: STRICT_DNS
    load_assignment:
      cluster_name: service_backend
      endpoints:
      - lb_endpoints:
        - endpoint: { address: { socket_address: { address: 10.0.0.11, port_value: 8080 }}}
envoy -c envoy.yaml &
curl -s http://localhost:10000/ -o /dev/null -w "%{http_code}\n"   # 200

实验二:用 admin 接口调试(Envoy 的可观测利器)

# Envoy 自带 admin 端口(配 admin: { address: ... port_value: 9901 })
curl -s localhost:9901/clusters     | head    # 各集群的后端、健康状态
curl -s localhost:9901/config_dump  | jq .     # 当前完整生效配置(含 xDS 下发的)
curl -s localhost:9901/stats | grep upstream_rq # 上游请求统计
curl -s localhost:9901/server_info             # 版本/状态

config_dump 在排查"xDS 到底下发了什么"时不可替代。

实验三:插一个故障注入 filter(混沌测试)

http_filters:
- name: envoy.filters.http.fault
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault
    delay:                                   # 给 50% 请求注入 5s 延迟
      percentage: { numerator: 50 }
      fixed_delay: 5s
- name: envoy.filters.http.router          # router 必须在最后
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

加一个 filter 就有了故障注入——这是 filter chain 可组合性的体现(也是 Istio 故障注入的底层)。


排错

现象根因解决
503 UH(no healthy upstream)Cluster 没有健康 endpoint查 /clusters、EDS 下发、健康检查
配置改了不生效改了静态文件但走的是 xDS看 config_dump 确认实际生效源
xDS 不同步控制面连接断、版本不一致查 Envoy↔控制面 gRPC 连接、/stats 的 xDS 指标
gRPC 调用失败没按 h2 配 ClusterCluster 加 http2_protocol_options(第07章)
filter 不执行filter 顺序错,router 不在最后router 必须是 HTTP filter 链最后一个
手写 YAML 太痛苦Envoy 配置本就繁琐生产用控制面(Istio)生成,别手写

本章小结

  • Envoy 的模型:Listener → Filter Chain → Route → Cluster → Endpoint,xDS 的每个 D 对应一层。
  • xDS(LDS/RDS/CDS/EDS/SDS/ADS) 让控制面动态热推配置,秒级生效、无 reload——这是它区别于 Nginx 的根本,也是 Mesh 选它的核心原因。
  • filter chain 责任链让能力可插拔(鉴权/限流/故障注入/Wasm)。
  • 强在动态、gRPC、可观测、mTLS、热重启;弱在配置复杂,故生产多由控制面生成。

下一章 第16章 Traefik / Caddy,看另一类现代代理如何走"自动化优先"路线:从容器标签自动发现路由、自动申请 HTTPS 证书,用便利换极致控制。

Prev
第14章 HAProxy:L4/L7、ACL、健康检查与 stick table
Next
第16章 Traefik / Caddy:自动服务发现与自动 HTTPS