4. Envoy 缓存过滤器:HTTP Cache Filter 配置、缓存后端与缓存键生成规则

Envoy 的 HTTP Cache Filter(envoy.filters.http.cache)是构建高性能反向代理与 API 网关的核心组件。它允许 Envoy 在内存或外部缓存后端中缓存上游响应,从而显著降低延迟、减少上游负载。本章将深入解析该过滤器的配置结构、支持的后端类型以及缓存键的生成规则,为后续的故障排查奠定基础。

4.1 HTTP Cache Filter 配置结构

HTTP Cache Filter 的配置通过 HttpCache 消息定义,核心字段包括缓存后端类型、缓存键配置、路由级覆盖以及最大缓存条目数。以下是一个典型的静态配置示例:

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }
    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
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains: ["*"]
              routes:
              - match: { prefix: "/api" }
                route: { cluster: backend_cluster }
                typed_per_filter_config:
                  envoy.filters.http.cache:
                    "@type": type.googleapis.com/envoy.extensions.filters.http.cache.v3.CacheConfig
                    enabled: true
                    cache_type: <cache_type>
                    # ... 其他配置
          http_filters:
          - name: envoy.filters.http.cache
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.cache.v3.CacheConfig
              enabled: true
              cache_type:
                name: envoy.extensions.http.cache.file_system_http_cache
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.cache.file_system_http_cache.v3.FileSystemHttpCacheConfig
                  max_cache_size_bytes: 1073741824  # 1GB
                  cache_path: "/tmp/envoy_cache"
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
关键配置项说明:
  • enabled:布尔值,控制过滤器是否生效。调试时可临时关闭。
  • cache_type:指定缓存后端实现,支持内存、文件系统、外部缓存(如 Redis)等。
  • typed_per_filter_config:可在路由级别覆盖全局缓存配置,实现细粒度控制。

4.2 缓存后端类型对比

Envoy 支持多种缓存后端,每种后端在性能、持久化、分布式能力上各有优劣。下表列出了三种主要后端的核心差异:

后端类型 实现名称 存储位置 持久化 分布式 典型场景
内存缓存 envoy.extensions.http.cache.simple_http_cache Envoy 进程堆内 否(重启丢失) 否(单机) 开发测试、低容量边缘节点
文件系统缓存 envoy.extensions.http.cache.file_system_http_cache 本地磁盘 是(重启保留) 否(单机) 中小规模部署、需要持久化
外部缓存(Redis) envoy.extensions.http.cache.redis_http_cache 外部 Redis 集群 是(取决于 Redis 配置) 是(多 Envoy 共享) 大规模集群、高可用、全局缓存
选型建议: 生产环境推荐使用外部缓存(Redis)以实现缓存一致性;文件系统缓存适合容器化部署中挂载持久卷的场景;内存缓存仅用于功能验证,切勿用于生产。

4.3 缓存键生成规则

缓存键(Cache Key)是 Envoy 判断缓存命中的唯一标识。默认情况下,Envoy 根据请求的 方法、Host、路径 和 查询参数 生成缓存键。开发者可以通过 CacheKey 配置自定义键生成逻辑。

4.3.1 默认缓存键结构

默认缓存键的生成公式如下:

cache_key = HTTP_METHOD + ":" + HOST + PATH + "?" + SORTED_QUERY_PARAMS

例如,请求 GET /api/users?id=123&role=admin 的默认缓存键为:

GET:example.com/api/users?id=123&role=admin
注意: 查询参数的顺序不影响缓存键,Envoy 会自动按字典序排序。但 请求头(如 Authorization、Accept-Encoding)默认不参与键生成,可能导致缓存污染。

4.3.2 自定义缓存键配置

通过 CacheKey 字段,可以指定哪些请求头参与键生成,或排除某些查询参数。以下示例配置了基于 Accept-Language 和 X-User-Tier 请求头的缓存键:

cache_config:
  cache_key:
    allowed_headers:
    - "Accept-Language"
    - "X-User-Tier"
    query_parameters_to_ignore:
    - "utm_source"
    - "utm_medium"

此时,请求 GET /api/data?utm_source=facebook&lang=en 的缓存键将忽略 utm_source,但包含 lang 参数和指定的请求头值。

4.4 缓存过滤器工作流程(SVG)

下图展示了 HTTP Cache Filter 在请求-响应生命周期中的核心处理流程:

Envoy HTTP Cache Filter 工作流程 HTTP Cache Filter 请求/响应处理流程 客户端请求 缓存键生成 & 查找 缓存命中 命中 缓存未命中 未命中 直接返回缓存响应 转发请求到上游 上游返回响应 缓存存储响应

4.5 缓存键生成规则详解(SVG)

缓存键的生成直接影响缓存命中率。下图展示了缓存键的组成元素及自定义配置的生效位置:

缓存键生成规则详解 缓存键生成规则与自定义配置 原始 HTTP 请求 缓存键生成器 最终缓存键 自定义配置 自定义配置影响缓存键的维度 • allowed_headers:指定参与键生成的请求头(如 Accept-Language、X-User-Tier) • query_parameters_to_ignore:排除不参与键生成的查询参数(如 utm_source) • host / scheme:可配置是否忽略 Host 或协议(HTTP/HTTPS)差异

4.6 常见配置陷阱与排查建议

陷阱 1:缓存键未包含认证信息
默认缓存键不包含 Authorization 头,导致不同用户的私有数据可能被错误共享。解决方案:在 allowed_headers 中添加 Authorization,或使用 Vary 响应头。
排查建议: 使用 Envoy 的 --log-level debug 启动,观察日志中的 cache_key 字段,确认键生成是否符合预期。例如:
[debug] cache filter: cache key = GET:example.com/api/data?lang=en
最佳实践:
  • 始终为包含敏感数据的路由配置自定义缓存键,避免跨用户缓存污染。
  • 对于高频变动的 API,考虑设置较短的 max-age 或使用 Cache-Control: no-cache。
  • 在容器化部署中,文件系统缓存路径应挂载持久卷,防止 Pod 重启导致缓存丢失。