原文地址: https://www.envoyproxy.io/docs/envoy/v1.28.0/intro/intro

Envoy 官网介绍文档的中文翻译(其他特性、其他协议)

  • 其他特性: 本地限速、全局限速、带宽限速、脚本扩展、IP透传、压缩库

  • 其他协议: gRPC、MongoDB、DynamoDB、Redis、Postgres)

  • 高级:在过滤期间共享数据、属性、普通匹配

其他特性

本地限流

Envoy 支持对 L4 连接进行本地(非分布式)限流,通过 本地限流监听器过滤器本地限流网络过滤器实现。 区别在于,*本地限流监听器过滤器<config_listener_filters_local_rate_limit>*在 TLS 握手和过滤器链匹配之前处理套接字。

Envoy 还支持通过 HTTP 本地限流过滤器 对 HTTP 请求进行本地限流。这可以在监听器级别或更具体的级别(例如:虚拟主机或路由级别)上激活。

最后,Envoy 还支持全局限流。本地限流可以与全局限流结合使用,以减少对全局限流服务的负载。

全局限流

虽然分布式断路器 在控制分布式系统中的吞吐量方面通常非常有效, 但在某些情况下它并不是很有效,这时就需要全局限流。 最常见的情况是大量主机转发到少数主机,平均请求延迟很低(例如,与数据库服务器的连接/请求)。 如果目标主机变得拥堵,下游主机将淹没上游集群。 在这种情况下,很难在每个下游主机上配置足够严格的断路器限制, 以确保系统在典型请求模式下的正常运行,同时在系统开始出现故障时仍能防止级联故障。 全局限流是解决这种情况的好方案。

Envoy 提供了两种全局限流实现:

  1. 每个连接或每个 HTTP 请求的限流检查。

  2. 基于配额的,带有定期负载报告,允许在多个 Envoy 实例之间公平地共享全局限流。 这种实现适用于大型 Envoy 部署,其中每秒请求负载很高,并且可能无法在所有 Envoy 实例之间均匀平衡。

每个连接或每个 HTTP 请求的限流

Envoy 直接与全局 gRPC 限流服务集成。 虽然任何实现定义的 RPC/IDL 协议的服务都可以使用, 但 Envoy 提供了一个用 Go 编写的参考实现, 该实现使用 Redis 后端。Envoy 的限流集成具有以下功能:

  • 网络级别限流过滤器:对于安装了过滤器的监听器上的每个新连接,Envoy 将调用限流服务。 配置指定了要限速的特定域和描述符集。这最终将对通过监听器的每秒连接数进行限速。 配置参考

  • HTTP 级别限流过滤器:对于安装了过滤器的监听器上的每个新请求,Envoy 将调用限流服务, 并且路由表指定应该调用全局限流服务。目标上游集群的所有请求以及从原始集群到目标集群的所有请求都可以进行限速。 配置参考

限流服务配置

请注意,Envoy 还支持本地限流。 本地限流可以与全局限流结合使用,以减少对全局限流服务的负载。 例如,本地令牌桶限流可以吸收可能淹没全局限流服务的非常大的负载突发。 因此,限流分为两个阶段进行。初始粗粒度限制由令牌桶限制执行,然后由细粒度全局限制完成工作。

基于配额的限流

目前还没有开源的限流服务参考实现。限流配额扩展目前可用于 Google Cloud Rate Limit Service。

基于配额的全局限流只能应用于 HTTP 请求。Envoy 将使用 HTTP 过滤器 配置 对请求进行分桶和请求配额分配。

限流配额服务配置

带宽限速

Envoy 支持通过 HTTP 带宽限制过滤器对 HTTP 请求和响应进行本地(非分布式)带宽限制。 这可以在监听器级别或更具体的级别(例如:虚拟主机或路由级别)全局激活。

脚本

Envoy 支持 Lua 脚本作为专用 HTTP 过滤器的一部分。

IP透传

什么是IP透传

作为一个代理,Envoy是一个IP端点:它有自己的IP地址,与任何下游请求的IP地址不同。 因此,当Envoy建立与上游主机的连接时,该连接的IP地址将与任何代理连接的IP地址不同。

有时,上游服务器或网络出于多种原因,可能需要知道原始的IP地址,称为下游远程地址,。一些例子包括:

  • 原始IP地址作为身份标识的一部分,

  • 原始IP地址用于实施网络策略,或

  • 原始IP地址用于审计。

Envoy支持多种方法将下游远程地址提供给上游主机。这些技术的复杂性和适用性各不相同。

Envoy还支持用于检测原始IP地址的扩展。 这可能在以下情况中非常有用:下面列出的任何技术都不适用于您的设置。 可用的扩展有两个: 自定义头扩展xff扩展

HTTP Headers

HTTP headers可以通过x-forwarded-for 头携带请求的原始IP地址。 上游服务器可以使用此头来确定下游远程地址。 Envoy还可以使用此头选择由Original Src HTTP Filter 使用的IP地址。

HTTP头方法有一些缺点:

  • 它仅适用于HTTP。

  • 它可能不受上游主机的支持。

  • 它需要仔细配置。

代理协议

HAProxy Proxy Protocol 定义了一种协议,用于在主TCP流之前通过TCP通信传输连接的元数据。 这些元数据包括源IP地址。 Envoy代理支持使用 代理协议过滤器 来利用这些信息,这有助于恢复下游远程地址,并将其传播到 x-forwarded-for头部。 此外,它还可以与 Original Src监听器过滤器 结合使用。最后,Envoy代理支持使用 代理协议传输套接字 生成此头部信息。

这是一个设置套接字的示例配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
clusters:
- name: service1
  connect_timeout: 0.25s
  type: strict_dns
  lb_policy: round_robin
  transport_socket:
    name: envoy.transport_sockets.upstream_proxy_protocol
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport
      config:
        version: V1
      transport_socket:
        name: envoy.transport_sockets.raw_buffer
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer
  ...

如果你计划将此套接字与HTTP连接管理器结合使用,需要考虑一些因素。由于代理协议是基于连接的协议,因此下游客户端之间不会重用上游连接。连接到Envoy的每个客户端都会与上游服务器建立新的连接。在建立连接之初,下游客户端信息会在发送任何其他数据之前转发给上游(注:这包括在TLS握手发生之前)。如果可能的话,应优先使用x-forwarded-for标头,因为使用此方法,Envoy能够重用上游连接。由于Envoy对下游和上游连接的处理是分开的,因此最好对上游连接强制执行短暂的空闲超时,因为当下游连接关闭时,Envoy不会自动关闭相应的上游连接。

代理协议的一些缺点:

  • 它只支持TCP协议。

  • 它需要上游主机支持。

原始源监听器过滤器

在受控的部署中,使用原始源监听器过滤器可以将下游远程地址复制到上游连接上。没有将元数据添加到上游请求或流中。相反,上游连接本身将以下游远程地址作为其源地址建立。此过滤器将与任何上游协议或主机一起工作。然而,它需要相当复杂的配置,并且由于路由约束,可能不支持所有部署。

原始源过滤器的一些缺点:

  • 它要求Envoy能够访问下游远程地址。
  • 它的配置相对复杂。
  • 由于连接池的限制,它可能会引入轻微的性能下降。
  • 不支持Windows。

原始源HTTP过滤器

在受控的部署中,可以使用 原始源HTTP过滤器 将下游远程地址复制到上游连接上。此过滤器与 原始源监听器过滤器 非常相似。主要区别在于,它可以从HTTP头中推断出原始源地址,这对于单个下游连接承载来自不同原始源地址的多个HTTP请求的情况非常重要。前端代理转发到边车代理的部署就是这种情况的示例。

此过滤器将与任何上游HTTP主机一起工作。然而,它需要相当复杂的配置,并且由于路由约束,可能不支持所有部署。

原始源过滤器的一些缺点:

  • 它要求Envoy经过适当配置,以便从x-forwarded-for标头中提取下游远程地址。
  • 它的配置相对复杂。
  • 由于连接池的限制,它可能会引入轻微的性能下降。

注意

此功能不支持Windows。

压缩库

底层实现

目前,Envoy使用zlib、brotli和zstd作为压缩库。

注意

zlib-ng是一个分支,托管了几个包含新优化的第三方贡献。 这些优化被认为对提高压缩性能很有用。 通过使用--define zlib=ng Bazel 选项, 可以将Envoy构建为使用zlib-ng而不是常规zlib。 用于构建zlib-ng的相关构建选项可以在这里评估。 目前,此选项仅在Linux上可用。

其他协议

gRPC

gRPC

gRPC是由Google开发的RPC框架。它使用协议缓冲区作为底层序列化/IDL格式。在传输层,它使用HTTP/2或更高版本进行请求/响应复用。Envoy在传输层和应用程序层都为gRPC提供了第一流的支持:

  • gRPC使用 trailer 来传递请求状态。Envoy是少数几个正确支持 trailer 的HTTP代理之一,因此也是少数几个能够传输gRPC请求和响应的代理之一。

  • 对于某些语言,gRPC的运行时相对不成熟。请参阅以下概述,了解有助于将gRPC引入更多语言的过滤器。

  • gRPC-Web由一个过滤器支持,该过滤器允许gRPC-Web客户端通过HTTP/1.1向Envoy发送请求,并将其代理到gRPC服务器。它正在积极开发中,预计将成为gRPC桥接过滤器的继任者。

  • gRPC-JSON转码器由一个过滤器支持,该过滤器允许RESTful JSON API客户端通过HTTP向Envoy发送请求,并将其代理到gRPC服务。

gRPC桥接

Envoy支持多个gRPC桥接:

  • grpc_http1_bridge 过滤器 允许gRPC请求通过HTTP/1.1发送到Envoy。Envoy然后将请求翻译为HTTP/2或HTTP/3,以便传输到目标服务器。响应被翻译回HTTP/1.1。安装后,桥接过滤器将收集每个RPC的统计数据以及全局HTTP统计数据的数组。

  • grpc_http1_reverse_bridge 过滤器允许将gRPC请求发送到Envoy,并在发送到上游时将其转换为HTTP/1.1。响应在发送到下游时被转换回gRPC。此过滤器还可以选择性地管理gRPC帧头,使得上游无需了解gRPC。

  • connect_grpc_bridge 过滤器允许将Buf Connect请求发送到Envoy。Envoy然后将请求翻译为gRPC以发送到上游。响应被转换回Buf Connect协议以发送回下游。需要时,HTTP/1.1请求将升级为HTTP/2或HTTP/3。

gRPC服务

除了在数据平面使用gRPC外,Envoy还将其用于控制平面(从管理服务器获取配置)以及过滤器(例如限速或授权检查)。我们将其称为gRPC服务。

在指定gRPC服务时,需要指定使用 Envoy gRPC客户端Google C++ gRPC客户端。 我们在下面讨论了这种选择的权衡。

Envoy gRPC客户端是gRPC的极简自定义实现,利用了Envoy的HTTP/2或HTTP/3上游连接管理。服务作为常规的Envoy集群进行指定,具有常规的 超时处理、重试、 端点发现/负载均衡/故障转移/负载报告、 断路器健康检查离群检测。 它们共享与Envoy数据平面相同的连接池机制。同样,集群统计信息可用于gRPC服务。由于客户端是最小的,因此不包括高级gRPC功能,例如OAuth2gRPC-LB查找。

Google C++ gRPC客户端基于Google在https://github.com/grpc/grpc上提供的gRPC参考实现。它提供了在Envoy gRPC客户端中缺少的高级gRPC功能。Google C++ gRPC客户端执行自己的负载均衡、重试、超时、端点管理等,与Envoy的集群管理无关。Google C++ gRPC客户端还支持自定义身份验证插件。

建议在大多数情况下使用Envoy gRPC客户端,而不需要Google C++ gRPC客户端中的高级功能。这提供了配置和监控的简单性。如果Envoy gRPC客户端缺少必要的功能,则应使用Google C++ gRPC客户端。

MongoDB

Envoy支持一个网络级别的MongoDB嗅探过滤器,具有以下功能:

  • MongoDB有线格式BSON解析器。

详细的MongoDB查询/操作统计信息,包括时间戳和路由集群的散列/多获取计数(including timings and scatter/multi-get counts for routed clusters.)。

  • 查询日志记录。

  • 通过$comment查询参数的每个调用方的统计信息。

  • 故障注入。

MongoDB过滤器是Envoy可扩展性和核心抽象的一个很好的例子,可用于在所有应用程序和MongoDB数据库之间进行过滤。它提供了一个宝贵的数据源,与应用程序平台和使用的特定MongoDB驱动程序无关。

MongoDB 代理过滤器配置指南

DynamoDB

Envoy支持一个HTTP级别的 DynamoDB 嗅探过滤器,具有以下功能:

  • DynamoDB API请求/响应解析器。

  • DynamoDB每个操作/每个表/每个分区的统计信息以及操作统计信息。

  • 从响应JSON解析的4xx响应的失败类型统计信息,例如ProvisionedThroughputExceededException。

  • 批处理操作的部分失败统计信息。

DynamoDB过滤器是Envoy在HTTP层上的可扩展性和核心抽象的一个很好的例子,可用于过滤所有应用程序与DynamoDB的通信。它提供了一个宝贵的数据源,与应用程序平台和使用的特定AWS SDK无关。

DynamoDB 过滤器配置

Redis

Envoy可以作为Redis代理,在集群的实例之间划分命令。在这种模式下,Envoy的目标是在可用性和分区容忍度之间保持一致性。这是将Envoy与Redis Cluster进行比较的关键点。Envoy被设计为最佳努力缓存,这意味着它不会尝试协调不一致的数据或保持集群成员的全局一致性视图。它还支持根据不同工作负载的访问模式、驱逐或隔离要求,将命令从不同的工作负载路由到不同的上游集群。

Redis项目提供了关于分区与Redis相关的全面参考。请参阅“分区:如何将数据拆分到多个Redis实例中”。

以下是Envoy Redis的一些功能:

  • Redis协议编解码器。
  • 基于哈希的分区。
  • Redis事务支持。
  • Ketama分布。
  • 详细的命令统计信息。
  • 主动和被动健康检查。
  • 哈希标签。
  • 前缀路由。
  • 独立的下游客户端和上游服务器身份验证。
  • 所有请求或仅写请求的请求镜像。
  • 控制读取请求的路由。仅与Redis Cluster一起工作。

计划中的未来增强功能:

  • 其他时间统计信息。
  • 断路器。
  • 对碎片化命令进行请求折叠。
  • 复制。
  • 内置重试。
  • 跟踪。

配置

有关过滤器配置的详细信息,请参阅Redis代理过滤器配置参考

相应的集群定义应配置为环哈希负载均衡

如果需要主动健康检查, 集群应配置为 自定义健康检查, 并将其配置为 Redis健康检查器

如果需要被动健康检查,还应配置异常检测

对于被动健康检查,连接超时、命令超时和连接关闭映射为5xx。来自Redis的所有其他响应都被计为成功。

Redis集群支持

Envoy提供了对Redis集群的支持。

当使用Envoy作为Redis集群的边车代理时,服务可以使用任何语言的非集群Redis客户端连接到代理,就像它是一个单节点Redis实例一样。Envoy代理将跟踪集群拓扑并根据规范将命令发送到正确的Redis节点。还可以向Envoy代理添加高级功能,例如从副本读取,而不是在每种语言中更新Redis客户端。

Envoy代理通过向集群中的随机节点发送定期的集群插槽命令来跟踪集群拓扑,并维护以下信息:

  • 已知节点的列表。

  • 每个分片的初级节点。

  • 进入或离开集群的节点。

Envoy代理支持通过cluster slots命令响应中的IP地址和主机名标识节点。在无法解析主机名的情况下,Envoy将定期重试解析所有节点,直到成功。无法解析副本只会跳过该副本。另一方面,如果设置了enable_redirection,并且收到包含主机名的MOVED或ASK响应,Envoy不会自动进行DNS查找,而是将错误原样传递给客户端。要使Envoy进行DNS查找并遵循重定向,您需要在连接池设置中配置DNS缓存选项dns_cache_config。有关如何启用重定向的DNS查找的配置示例,请参阅过滤器配置参考

有关拓扑配置的详细信息,请参阅Redis Cluster v3 API参考

每个Redis集群都有自己的额外统计树,其根在 cluster..redis_cluster. 下,具有以下统计信息:

名称类型描述
max_upstream_unknown_connections_reachedCounter在达到连接池的max_upstream_unknown_connections限制后,无法创建到未知主机的上游连接的次数。经过重定向后,不创建上游到未知主机的连接。
upstream_cx_drainedCounter在关闭之前,排空所有活跃请求的上游连接的总数。排空所有活跃请求的上游连接。
upstream_commands.upstream_rq_timeHistogram所有类型请求的上游请求时间的直方图。所有类型请求的上游请求时间直方图。

通过设置 enable_command_stats 开启每个集群的命令统计:

名称类型描述
upstream_commands.[command].successCounter特定 Redis 命令成功请求的总数
upstream_commands.[command].failureCounter特定 Redis 命令失败或取消的请求总数
upstream_commands.[command].totalCounter特定 Redis 命令的请求总数(成功和失败的总和)
upstream_commands.[command].latencyHistogram特定 Redis 命令请求的延迟

事务

Envoy 支持事务 (MULTI)。其使用方式与常规 Redis 相同:您使用 MULTI 开始事务,然后使用 EXEC 执行它。在事务中,只支持 Envoy 支持的命令(见下文)和单键命令,即不支持 MGET 和 MSET。DISCARD 命令也支持。

当在 Redis 集群模式下工作时,Envoy 会将事务中的所有命令转发给处理事务中的第一个基于键的命令的节点。用户有责任确保事务中的所有键都映射到相同的哈希槽,因为命令不会被重定向。

支持的命令

在协议层面,支持管道。在可能的情况下使用管道以获得最佳性能。

在命令级别,Envoy 只支持能够可靠地哈希到服务器的命令。AUTH 和 PING 是唯一的例外。如果下游配置了密码,则 AUTH 将由 Envoy 在本地处理,并且在身份验证成功之前,不会处理其他命令。如果为集群配置了上游服务器身份验证密码,Envoy 将与上游服务器连接时透明地发出 AUTH 命令。Envoy 会立即对 PING 做出响应,发送 PONG。不允许 PING 的参数。所有其他受支持的命令必须包含一个键。受支持的命令在功能上与原始 Redis 命令相同,除非在故障场景中可能有所不同。

每个命令的使用参考官方 Redis 命令参考

支持的命令列表

故障模式

如果 Redis 抛出错误,我们将该错误作为命令的响应传递。Envoy 将 Redis 带有错误数据类型的响应视为正常响应,并将其传递给调用者。

Envoy 还可以在响应客户端时生成自己的错误。

Envoy 错误对照表

错误含义
no upstream host在为该键选择的环位置上,环哈希负载均衡器没有可用的健康主机。
upstream failure后端未在超时时间内响应或关闭了连接。
invalid request由于数据类型或长度,命令被命令拆分器的第一阶段拒绝。
unsupported command该命令未被 Envoy 识别,因此无法提供服务,因为它无法被哈希到后端服务器。
finished with n errors分片命令(例如 DEL)将返回收到的错误总数,如果有收到任何错误。
upstream protocol error分片命令收到了意外的数据类型或后端响应不符合 Redis 协议。
wrong number of arguments for command某些命令在 Envoy 中检查参数的数量是否正确。
NOAUTH Authentication required.该命令被拒绝,因为设置了下游认证密码,而客户端未成功通过身份验证。
ERR invalid password由于密码无效,认证命令失败。
ERR Client sent AUTH, but no password is set收到了认证命令,但没有配置下游认证密码。

在 MGET 的情况下,无法获取的每个单独的键都会生成一个错误响应。例如,如果我们获取五个键,其中两个键的后端超时,我们将在每个值的位置上获得一个错误响应。

1
2
3
4
5
6
$ redis-cli MGET a b c d e
1) "alpha"
2) "bravo"
3) (error) upstream failure
4) (error) upstream failure
5) "echo"

Postgres

Envoy 支持一个网络级别的 Postgres 嗅探过滤器,以增加网络可观察性。通过使用 Postgres 代理,Envoy 能够解码 Postgres 前端/后端协议,并从解码的信息中收集统计数据。

Postgres 过滤器的主要目标是捕获运行时统计信息,而不会对 Postgres 上游服务器产生任何影响或生成任何负载,它对上游服务器是透明的。该过滤器目前提供以下功能:

  • 解码非 SSL 流量,忽略 SSL 流量。
  • 解码会话信息。
  • 在转发上游之前对传入非 SSL 流量进行编码。
  • 捕获事务信息,包括提交和回滚。
  • 公开不同类型的语句(INSERT、DELETE、UPDATE 等)的计数器。这些计数器根据解码的后端 CommandComplete 消息进行更新,而不是通过解码客户端发送的 SQL 语句。
  • 计算前端、后端和未知消息的数量。
  • 识别错误和通知后端响应。

Postgres 过滤器解决了 Postgres 部署中的一个显著问题:收集这些信息要么给服务器带来额外的负载;要么需要从服务器拉取查询元数据的查询,有时需要外部组件或扩展。此过滤器提供宝贵的可观察性信息,而不会影响上游 Postgres 服务器的性能或要求安装任何软件。

Postgres 代理过滤器配置参考

高级

在过滤期间共享数据

Envoy 提供了以下机制,用于在过滤器之间以及与其他核心子系统(例如访问日志)之间的传输传输配置、元数据和每个请求/连接的状态。

静态状态

静态状态是在配置加载时指定的任何不可变状态(例如通过 xDS)。静态状态有三种类型:

元数据

Envoy 配置的几个部分(例如监听器、路由、集群)包含一个元数据,其中可以编码任意键值对。常见的模式是使用反向 DNS 格式的过滤器名称作为键,并将过滤器特定的配置元数据编码为值。这种元数据是不可变的,并且在所有请求/连接之间共享。此类配置元数据通常在引导时间或作为 xDS 的一部分提供。例如,HTTP 路由中的加权集群使用元数据来指示对应于加权集群的端点的标签。另一个例子是,子集负载均衡器使用路由条目中的元数据来选择集群中适当的端点。

类型化元数据

元数据本身是无类型的。在对其执行操作之前,调用者通常将其转换为类型化的类对象。当执行多次转换时(例如,对于每个请求流或连接),转换成本变得不可忽略。类型化元数据通过允许过滤器注册特定键的一次性转换逻辑来解决这个问题。传入的配置元数据(通过 xDS)在配置加载时转换为类对象。过滤器然后可以在运行时获得类型化的元数据变体(按请求或连接),从而消除了在请求/连接处理期间过滤器需要反复将 ProtobufWkt::Struct 转换为某些内部对象的需要。

例如,一个过滤器希望在 ClusterInfo 中的 xxx.service.policy 键的元数据上有一个方便的包装类。它可以注册一个继承自 ClusterTypedMetadataFactoryServicePolicyFactory 工厂。该工厂将 ProtobufWkt::Struct 转换为 ServicePolicy 类实例(继承自 FilterState::Object)。当创建 Cluster 时,将创建并缓存关联的 ServicePolicy 实例。请注意,类型化元数据不是新来源的元数据。它是从配置中指定的元数据中获取的。实现了 serializeAsProto 方法的 FilterState::Object 可以配置在访问记录器中记录它。

HTTP 路由特定过滤器配置

在 HTTP 路由中,typed_per_filter_config 允许 HTTP 过滤器除了全局过滤器配置外,还具有特定于虚拟主机/路由的配置。此配置被转换并嵌入到路由表中。HTTP 过滤器实现可以将路由特定的过滤器配置视为对全局配置的替换或增强。例如,HTTP 故障过滤器使用此技术提供按路由的故障配置。

typed_per_filter_config 是一个 map<string, google.protobuf.Any>。连接管理器会遍历此映射,并调用 filter 工厂接口 createRouteSpecificFilterConfigTyped 来解析/验证结构值,并将其转换为与路由本身一起存储的有类型类对象。HTTP 过滤器可以在请求处理期间查询特定于路由的过滤器配置。

动态状态

动态状态是针对每个网络连接或每个HTTP流生成的。如果生成状态的过滤器需要,动态状态可以是可变的。

Envoy::Network::ConnectionEnvoy::Http::Filter 提供了一个 StreamInfo 对象,该对象包含有关当前 TCP 连接和 HTTP 流(即 HTTP 请求/响应对)的信息。StreamInfo 包含一组固定的属性,作为类定义的一部分(例如,HTTP 协议、请求的服务器名称等)。此外,它还提供了一个机制来将类型化的对象存储在地图中(map<string, FilterState::Object>)。存储在每个过滤器中的状态可以是只写一次(不可变)或可多次写入(可变)。

请参阅众所周知的动态元数据众所周知的过滤器状态,以获取动态元数据和过滤器状态对象的参考列表。

过滤器状态共享

过滤器状态对象与父流的生命周期绑定。然而,如果在创建期间将一个下游对象标记为与上游连接共享,该对象将与上游连接的过滤器状态共享,其生命周期将扩展到原始流之外。任何上游 TCP 或 HTTP 过滤器都可以访问共享的对象。上游传输套接字也可以读取共享的对象并自定义上游传输的创建。例如,内部上游传输套接字将共享对象的引用复制到内部连接的下游过滤器状态中。

与上游共享的过滤器状态对象还会影响连接池的决策,如果它们实现了哈希接口。每当添加可共享的可哈希对象时,就会为每个不同的哈希值创建一个上游连接,以确保这些对象不会被同一上游连接的后续下游请求覆盖。例如,自定义 HTTP 过滤器可以从特殊头部的值创建一个可共享的可哈希对象。在这种情况下,对于每个不同的特殊头部值,都会创建一个单独的上游连接,以确保具有不同头部值的两个请求不会共享同一个上游连接。相同的程序对每个单独的可哈希对象适用,为对象的值的不同组合创建上游连接的组合矩阵。

属性

属性是指由 Envoy 在请求和连接处理过程中提供的上下文相关属性。它们通过一个由点分隔的路径进行命名(例如,request.path),具有固定的类型(例如,stringint),并根据上下文可能出现或缺失。属性通过以下方式暴露:

  • 通过RBAC过滤器在CEL运行时中暴露属性。
  • 通过get_property ABI方法在Wasm扩展中暴露属性。

属性值类型限制为:

  • string:UTF-8字符串
  • bytes:字节缓冲区
  • int:64位有符号整数
  • uint:64位无符号整数
  • bool:布尔值
  • list:值列表
  • map:具有字符串键的关联数组
  • timestamp:时间戳,如Timestamp指定
  • duration:持续时间,如Duration指定
  • Protocol buffer message types(协议缓冲区消息类型)

CEL为抽象类型提供了标准辅助函数,例如对timestamp值的getMonth。请注意,整数字面量(例如,7)的类型为int,这与uint(例如,7u)不同,并且不自动进行算术转换(要明确转换,请使用uint(7))。

Wasm扩展接收的属性值是一个根据属性类型进行序列化的缓冲区。字符串和字节按原样传递,整数直接作为64位传递,时间戳和持续时间近似为纳秒,结构化值被递归地转换为一对序列。

请求属性

以下请求属性通常在初始请求处理时可用,这使得它们适合用于RBAC策略。

request.* 属性仅在http过滤器中可用。

属性类型描述
request.pathstringURL的路径部分
request.url_pathstring不带查询字符串的URL路径部分
request.hoststringURL的主机部分
request.schemestringURL的方案部分,例如:“http”
request.methodstring请求方法,例如:“GET”
request.headersmap<string, string>按头名称小写排序的所有请求头的映射
request.refererstringReferer请求头
request.useragentstringUser-Agent请求头
request.timetimestamp接收第一字节的时间
request.idstring与x-request-id头值对应的请求ID
request.protocolstring请求协议(“HTTP/1.0”,“HTTP/1.1”,“HTTP/2”或“HTTP/3”)
request.querystringURL的查询部分,格式为“name1=value1&name2=value2” 。

在请求完成时,request.headers关联数组中的Header值是使用逗号连接的多个值。

一旦请求完成,将提供其他属性:

属性类型描述
request.durationduration请求的总持续时间
request.sizeint请求体的尺寸。如果可用,则使用内容长度头。
request.total_sizeint请求的总大小,包括大致未压缩的头部大小

响应属性

响应属性仅在请求完成后可用。

response.* 属性仅在http过滤器中可用。

属性类型描述
response.codeint响应的HTTP状态码
response.code_detailsstring内部响应代码详细信息(可能会有所更改)
response.flagsint以位向量编码的除标准响应码之外的响应附加详细信息
response.grpc_statusint响应的gRPC状态码
response.headersmap<string, string>按头名称小写索引的所有响应头
response.trailersmap<string, string>按尾部名称小写索引的所有响应尾部
response.sizeint响应体的尺寸
response.total_sizeint包括大致未压缩的头部和尾部大小的响应的总大小

连接属性

一旦下游连接建立,以下属性即可用(这也适用于HTTP请求,使其适合RBAC):