2. Envoy 架构基础:核心组件与请求处理流程

Envoy 是一个高性能、可编程的 L3/L4/L7 代理,其架构围绕一组明确定义的核心组件构建。理解 Listener、Cluster 和 Filter 这三个核心概念,以及它们如何协同处理请求,是掌握 Envoy 缓存机制和故障排查的基石。

2.1 三大核心组件

组件 职责 类比(反向代理场景)
Listener 定义 Envoy 如何监听入站流量。它绑定 IP 地址和端口,并配置用于处理连接的过滤器链。 公司前台接待处,负责接收所有访客(请求)并引导至相应部门。
Cluster 定义 Envoy 将流量转发到的上游服务端点集合。包含服务发现、健康检查、负载均衡策略等配置。 公司内部的具体业务部门(如技术部、市场部),每个部门有若干员工(端点)处理任务。
Filter 可插拔的处理单元,在请求/响应流经 Listener 或 Cluster 时执行特定逻辑(如路由、缓存、限流、协议转换)。 接待处到部门之间的处理流程:安全检查、登记、分派任务等环节。
关键认知: Listener 负责“入”,Cluster 负责“出”,Filter 负责“处理”。缓存功能正是通过特定的 HTTP 缓存 Filter 在请求处理路径中实现的。

2.2 请求处理流程(L3/L4 → L7)

Envoy 的请求处理遵循一个清晰的管道模型,从底层网络连接逐步上升到应用层协议处理。下图展示了从客户端请求到达 Envoy 到被转发至上游服务的完整路径。

Envoy 请求处理流程架构图 Envoy 请求处理流程(L3/L4 → L7) 客户端 Listener (IP:Port 绑定) L3/L4 连接接受 Filter Chain (L4) TLS 终止 / 代理协议 原始连接处理 HTTP 连接管理 HTTP/1.1 / HTTP/2 协议解码 HTTP Filter Chain (L7) Router / 缓存 / 限流 / 故障注入 请求头/体修改 路由决策 Cluster 选择 & 负载均衡 服务发现 / 健康检查 轮询 / 最少连接 / 一致性哈希 上游端点 (后端服务) 说明: 缓存 Filter 通常位于 HTTP Filter Chain 中,在 Router Filter 之前执行。命中缓存则直接返回,不再转发至 Cluster。 故障排查时,需依次检查 Listener 配置、Filter 顺序、Cluster 端点状态。

2.3 核心流程步骤详解

  1. 连接接受(Listener):Envoy 通过配置的 Listener 在指定端口(如 80、443)接受来自客户端的 TCP 连接。
  2. L4 过滤器处理:连接建立后,数据流经 L4 过滤器链。常见操作包括 TLS 握手终止、代理协议解析等。此阶段不解析应用层协议。
  3. HTTP 连接管理:如果流量是 HTTP 协议,Envoy 的 HTTP 连接管理器(HCM)会解码 HTTP 请求(包括头部和体),将字节流转换为内部请求对象。
  4. L7 HTTP 过滤器链:请求对象按顺序通过 HTTP 过滤器链。这是 Envoy 最灵活的部分,缓存功能(如 envoy.filters.http.cache)和路由功能(envoy.filters.http.router)均在此实现。
    • 缓存 Filter 通常位于 Router Filter 之前。它检查请求是否可缓存、是否命中缓存。若命中,直接构造响应并返回,跳过后续转发步骤。
    • Router Filter 根据请求头(Host、Path 等)匹配路由规则,决定将请求转发到哪个 Cluster。
  5. Cluster 负载均衡:Router Filter 选定目标 Cluster 后,Envoy 根据该 Cluster 配置的负载均衡策略(如轮询、一致性哈希)选择一个健康的上游端点。
  6. 转发与响应:Envoy 将请求转发至选定的上游端点,接收响应,然后响应以相反路径流经过滤器链(允许响应 Filter 处理),最终返回给客户端。
缓存故障排查要点: 在排查缓存未命中或缓存异常时,应重点检查:
  • Filter 顺序:缓存 Filter 是否在 Router Filter 之前?
  • 路由配置:请求是否匹配了正确的路由,从而进入预期的 Cluster?
  • Cluster 状态:上游端点是否健康?负载均衡策略是否一致?

2.4 组件配置示例(片段)

以下 YAML 配置片段展示了 Listener、Filter 和 Cluster 的关联关系:

static_resources:
  listeners:
  - name: listener_http
    address:
      socket_address: { address: 0.0.0.0, port_value: 80 }
    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
          codec_type: AUTO
          stat_prefix: ingress_http
          http_filters:
          - name: envoy.filters.http.cache           # <-- 缓存 Filter 在前
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.cache.v3.CacheConfig
              ...
          - name: envoy.filters.http.router          # <-- 路由 Filter 在后
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route: { cluster: service_cluster }

  clusters:
  - name: service_cluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: service-backend, port_value: 8080 }
常见配置错误: 若将 Router Filter 配置在 Cache Filter 之前,Envoy 会先执行路由决策再尝试缓存,这可能导致缓存策略失效或产生非预期的缓存行为。务必保证缓存 Filter 在路由 Filter 之前声明。