外部应用负载平衡器的请求分配

本文档深入探讨了外部应用负载平衡器如何处理连接、路由流量和保持会话亲和性。

连接的工作原理

Trusted Cloud的外部应用负载平衡器(全球级和区域级)使用分布式代理 (GFE) 或 Envoy 管理的子网来简化路由。借助可配置的超时时间、TLS 终结和内置安全性,它们可确保在全球或区域范围内实现合规且可伸缩的应用交付。

区域级外部应用负载均衡器连接

区域级外部应用负载均衡器是在 Envoy 代理上实现的托管式服务。区域级外部应用负载均衡器使用名为代理专用子网的共享子网预配一组 IP 地址,供 Google 用于代表您运行 Envoy 代理。此代理专用子网的 --purpose 标志设置为 REGIONAL_MANAGED_PROXY。特定网络和区域中的所有基于 Envoy 的区域负载均衡器共享此子网。

客户端使用负载均衡器的 IP 地址和端口连接到负载均衡器。客户端请求会定向到与客户端位于同一区域的代理专用子网。负载均衡器终止客户端请求,然后打开从代理专用子网到您的后端的新连接。因此,从负载均衡器发送的数据包具有来自代理专用子网的来源 IP 地址。

根据后端服务配置,Envoy 代理用于连接到后端的协议可以是 HTTP、HTTPS 或 HTTP/2。如果是 HTTP 或 HTTPS,则 HTTP 版本为 HTTP 1.1。根据 HTTP 1.1 规范的规定,HTTP keepalive 默认处于启用状态。Envoy 代理将客户端 HTTP keepalive 超时和后端 keepalive 超时设置为默认值 600 秒。您可以更新客户端 HTTP keepalive 超时,但后端 keepalive 超时值是固定的。您可以通过设置后端服务超时来配置请求/响应超时。如需了解详情,请参阅超时和重试

客户端与负载均衡器的通信

  • 客户端可以使用 HTTP 1.1 或 HTTP/2 协议与负载均衡器进行通信。
  • 使用 HTTPS 时,新型客户端默认使用 HTTP/2。此配置是在客户端而非 HTTPS 负载均衡器上控制的。
  • 您无法通过更改负载均衡器的配置来停用 HTTP/2。不过,您可以将某些客户端配置为使用 HTTP 1.1 而不是 HTTP/2。例如,在 curl 中,请使用 --http1.1 参数。
  • 外部应用负载均衡器支持 HTTP/1.1 100 Continue 响应。

如需查看每种模式下外部应用负载均衡器转发规则所支持的协议的完整列表,请参阅负载均衡器功能

客户端数据包的来源 IP 地址

后端所识别的数据包的来源 IP 地址不是负载均衡器的Trusted Cloud 外部 IP 地址。换句话说,存在两个 TCP 连接。

  • 连接 1,从原始客户端到负载均衡器(代理专用子网):

    • 来源 IP 地址:原始客户端(如果客户端位于 NAT 网关或转发代理后面,则为外部 IP 地址)。
    • 目标 IP 地址:您的负载均衡器的 IP 地址。
  • 连接 2,从负载均衡器(代理专用子网)到后端虚拟机或端点):

    • 来源 IP 地址代理专用子网中的 IP 地址,该 IP 地址在与负载均衡器部署在同一区域和网络的所有基于 Envoy 的负载均衡器之间共享。

    • 目的地 IP 地址:VPC 网络中的后端虚拟机或容器的内部 IP 地址。

特殊路由路径

Trusted Cloud 使用未在您的 VPC 网络中定义的特殊路由来为以下类型的流量路由数据包:

Trusted Cloud 使用代理专用子网的子网路由来为以下类型的流量路由数据包:

  • 使用分布式 Envoy 健康检查时的流量。

对于区域级外部应用负载均衡器, Trusted Cloud 使用开源 Envoy 代理来终止发送到负载均衡器的客户端请求。负载均衡器会终止 TCP 会话并打开从区域的代理专用子网到后端的新 TCP 会话。在您的 VPC 网络中定义的路由可以实现从 Envoy 代理到后端以及从后端到 Envoy 代理的通信。

TLS 终结

下表总结了外部应用负载均衡器如何处理 TLS 终结。

负载均衡器模式 TLS 终结
区域级外部应用负载均衡器 TLS 在位于用户所选区域中的代理专用子网的 Envoy 代理上终结。如果您需要对 TLS 终结所在的区域进行地理位置控制,请使用此负载均衡器模式。

超时和重试

后端服务超时

可配置的后端服务超时表示负载均衡器等待后端处理 HTTP 请求并返回相应的 HTTP 响应的最长时间。除无服务器 NEG 外,后端服务超时的默认值为 30 秒。

例如,如果您要下载一个 500 MB 的文件,并且后端服务超时值为 90 秒,则负载均衡器期望后端在 90 秒内传送整个 500 MB 的文件。有时,配置的后端服务超时值可能会不够长,使得后端无法发送其完整的 HTTP 响应。在这种情况下,如果负载均衡器至少收到来自后端的 HTTP 响应标头,则负载均衡器会返回完整响应标头以及在后端服务超时内尽可能获取的响应正文部分。

建议您将后端服务超时设置为您希望后端处理 HTTP 响应所需的最长时间。如果后端上运行的软件需要更多时间来处理 HTTP 请求并返回完整响应,建议您延长后端服务超时时间。

后端服务超时接受 12,147,483,647 秒之间的值,但过大的值不是切实可行的配置选项。Trusted Cloud 也不保证底层 TCP 连接在后端服务超时的整个期间保持打开状态。 客户端系统必须实现重试逻辑,而不是依赖 TCP 连接长时间保持打开状态。

如需配置后端服务超时,请使用以下方法之一:

控制台

修改负载均衡器后端服务的超时字段。

gcloud

使用 gcloud compute backend-services update 命令修改后端服务资源的 --timeout 参数。

客户端 HTTP keepalive 超时

负载均衡器的客户端 HTTP keepalive 超时必须大于下行客户端或代理使用的 HTTP keepalive(TCP 空闲)超时。如果下行客户端的 HTTP keepalive(TCP 空闲)超时大于负载均衡器的客户端 HTTP keepalive 超时,则可能会出现竞态条件。从下行客户端的角度来看,已建立的 TCP 连接可以空闲的时间超过负载均衡器允许的时长。这意味着,在负载均衡器认为 TCP 连接已关闭后,下行客户端可以发送数据包。发生这种情况时,负载均衡器会以 TCP 重置 (RST) 数据包进行响应。

当客户端 HTTP keepalive 超时到期时,GFE 或 Envoy 代理会向客户端发送 TCP FIN 以正常关闭连接。

后端 HTTP keepalive 超时

负载均衡器的第二个 TCP 连接可能不会在每次请求后关闭;它们可以保持打开状态,以处理多个 HTTP 请求和响应。后端 HTTP keepalive 超时定义了负载均衡器与后端之间的 TCP 空闲超时。后端 HTTP keepalive 超时不适用于 WebSocket。

后端 keepalive 超时固定为 10 分钟(600 秒),无法更改。这有助于确保负载均衡器保持空闲连接至少 10 分钟。在此期限结束后,负载均衡器可以随时向后端发送终止数据包。

负载均衡器的后端 keepalive 超时必须小于后端上运行的软件使用的 keepalive 超时。这样可以避免出现竞态条件,在竞态条件下,后端的操作系统可能通过 TCP 重置 (RST) 关闭 TCP 连接。由于负载均衡器的后端 keepalive 超时不可配置,因此您必须配置后端软件,以使其 HTTP keepalive(TCP 空闲)超时值大于 600 秒。

当后端 HTTP keepalive 超时到期时,GFE 或 Envoy 代理会向后端虚拟机发送 TCP FIN 以正常关闭连接。

下表列出了修改常用 Web 服务器软件的 keepalive 超时值需要进行的更改。

Web 服务器软件 参数 默认设置 推荐设置
Apache KeepAliveTimeout KeepAliveTimeout 5 KeepAliveTimeout 620
nginx keepalive_timeout keepalive_timeout 75s; keepalive_timeout 620s;

GKE Ingress 支持 WebSocket 协议。

非法的请求和响应处理

HTTP(S) 负载均衡器会因为许多原因阻止客户端请求和后端响应到达后端或客户端。有些是为了严格遵循 HTTP/1.1 合规要求,有些则是为了避免数据意外传入或传出后端。您无法停用这些检查。

为了满足 HTTP/1.1 合规要求,负载均衡器会阻止以下请求:

  • 它无法解析请求的第一行。
  • 标头缺少冒号 (:) 分隔符。
  • 标头或第一行包含无效字符。
  • 内容长度不是有效数字,或者有多个内容长度标头。
  • 存在多个传输编码密钥,或者存在无法识别的传输编码值。
  • 存在非数据块正文且没有指定内容长度。
  • 正文数据块无法解析。这是某些数据到达后端的唯一情况。负载均衡器会在收到无法解析的数据块时关闭与客户端和后端的连接。

请求处理

如果存在以下任一情况,负载均衡器便会阻止请求:

  • 请求标头和请求网址的总大小超过外部应用负载均衡器的请求标头大小上限。
  • 请求方法不允许有正文,但请求有正文。
  • 请求包含 Upgrade 标头,但 Upgrade 标头并没有用来启用 WebSocket 连接。
  • HTTP 版本未知。

响应处理

如果存在以下任一情况,负载均衡器便会阻止后端的响应:

  • 响应标头的总大小超过外部应用负载均衡器的响应标头大小上限。
  • HTTP 版本未知。

在同时处理请求和响应时,负载均衡器可能会移除或覆盖 HTTP/1.1 中的跃点标头,然后将其转发到预期目标。

流量分配

将后端实例组或 NEG 添加到后端服务时,您可指定一种均衡模式,用于定义衡量后端负载和目标容量的方法。外部应用负载均衡器支持两种平衡模式:

  • 对于实例组或 NEG,RATE 是每秒的目标最大请求次数 (RPS) 或查询次数 (QPS)。如果所有后端都达到或超过容量,则实际 RPS/QPS 可以超过目标最大 RPS/QPS。

  • UTILIZATION 是实例组中虚拟机的后端利用率。

流量在后端之间的分配方式取决于负载均衡器的模式。

区域级外部应用负载均衡器

对于区域级外部应用负载均衡器,流量分配取决于负载均衡模式和负载均衡位置政策。

均衡模式决定了应发送到每个组(实例组或 NEG)的流量的权重和比例。负载均衡位置政策 (LocalityLbPolicy) 决定了组中后端的负载均衡方式。

当后端服务收到流量时,它首先会根据后端的均衡模式将流量定向到后端(实例组或 NEG)。选择后端后,系统会根据负载均衡位置政策在后端组中的实例或端点之间分配流量。

详情请参阅以下内容:

会话亲和性

在应用负载平衡器的后端服务上配置的会话亲和性会尽力尝试将来自特定客户端的请求发送到同一个后端,只要运行状况良好的后端实例或端点的数量保持不变,并且之前选择的后端实例或端点未达到容量上限。均衡模式的目标容量决定了后端达到容量上限的条件。

下表列出了不同的应用负载平衡器支持的不同类型的会话亲和性选项。在下一部分会话亲和性类型中,我们将更详细地讨论每种会话亲和性类型。

表格:受支持的会话亲和性设置
产品 会话粘性选项
  • 无 (NONE)
  • 客户端 IP (CLIENT_IP)
  • 生成的 Cookie (GENERATED_COOKIE)
  • 标头字段 (HEADER_FIELD)
  • HTTP Cookie (HTTP_COOKIE)
  • 基于有状态 Cookie 的亲和性 (STRONG_COOKIE_AFFINITY)

另外还需注意以下事项:

  • 负载均衡位置政策 (localityLbPolicy) 的有效默认值会根据您的会话亲和性设置而变化。如果未配置会话亲和性(即会话亲和性保持默认值 NONE),则 localityLbPolicy 的默认值为 ROUND_ROBIN。 如果会话亲和性设置为 NONE 以外的值,则 localityLbPolicy 的默认值为 MAGLEV

配置会话亲和性时请注意以下几点:

  • 为进行身份验证或为了安全起见,请勿依赖会话亲和性。除了基于有状态 Cookie 的会话亲和性之外,只要服务后端和运行状况良好的后端数量发生变化,会话亲和性就会被破坏。如需了解详情,请参阅失去会话亲和性

  • --session-affinity--subsetting-policy 标志的默认值都是 NONE,并且一次只能将其中一个设置为不同的值。

会话亲和性的类型

外部应用负载平衡器的会话亲和性可分为以下类别之一:
  • 基于哈希的会话亲和性(NONECLIENT_IP
  • 基于 HTTP 标头的会话亲和性 (HEADER_FIELD)
  • 基于 Cookie 的会话亲和性(GENERATED_COOKIEHTTP_COOKIESTRONG_COOKIE_AFFINITY

基于哈希的会话亲和性

对于基于哈希的会话亲和性,负载均衡器使用一致的哈希算法来选择符合条件的后端。会话亲和性设置决定了使用 IP 标头中的哪些字段来计算哈希。

基于哈希的会话亲和性可以是以下类型:

将会话亲和性设置为 NONE 表示没有会话亲和性。这意味着未明确配置任何会话亲和性选项。

始终会执行哈希处理来选择后端。将会会话亲和性设置为 NONE 表示负载均衡器使用 5 元组哈希来选择后端。5 元组哈希由源 IP 地址、源端口、协议、目标 IP 地址和目标端口组成。

会话亲和性的默认值为 NONE

客户端 IP 亲和性

客户端 IP 会话亲和性 (CLIENT_IP) 是根据数据包的源 IP 地址和目标 IP 地址创建的二元组哈希。客户端 IP 亲和性会将来自同一客户端 IP 地址的所有请求转发到同一后端,只要该后端具有容量且健康状况良好。

使用客户端 IP 亲和性时,请注意以下几点:

  • 只有在数据包直接发送到负载均衡器时,数据包目标 IP 地址才与负载均衡器转发规则的 IP 地址相同。
  • 如果数据包在传送到 Trusted Cloud 负载均衡器之前由中间 NAT 或代理系统进行处理,则数据包源 IP 地址可能与与原始客户端关联的 IP 地址不一致。在许多客户端共享同一有效源 IP 地址的情况下,某些后端虚拟机可能会比其他后端虚拟机接收更多连接或请求。

基于 HTTP 标头的会话亲和性

借助标头字段亲和性 (HEADER_FIELD),系统会根据后端服务的 consistentHash.httpHeaderName 字段中的 HTTP 标头值将请求路由到后端。为了将请求分配到所有可用的后端,每个客户端都需要使用不同的 HTTP 标头值。

如果满足以下条件,则支持标头字段亲和性:

  • 负载均衡位置政策为 RING_HASHMAGLEV
  • 后端服务的 consistentHash 指定 HTTP 标头的名称 (httpHeaderName)。

基于 Cookie 的会话亲和性可以是以下类型:

如果您使用生成的 Cookie 亲和性 (GENERATED_COOKIE),负载平衡器会在 Set-Cookie 标头中添加一个 HTTP Cookie,以响应初始 HTTP 请求。

生成的 Cookie 的名称因负载平衡器的类型而异。

产品 Cookie 名称
全局外部应用负载均衡器 GCLB
传统应用负载均衡器 GCLB
区域外部应用负载均衡器 GCILB

生成的 Cookie 的路径属性始终是正斜杠 (/),因此它适用于同一网址映射上的所有后端服务(前提是其他后端服务也使用生成的 Cookie 亲和性)。

您可以使用 affinityCookieTtlSec 后端服务参数将 Cookie 的存留时间 (TTL) 值配置为介于 01,209,600 秒(含边界值)之间的值。如果未指定 affinityCookieTtlSec,则默认 TTL 值为 0

当客户端在 HTTP 请求的 Cookie 请求标头中包含生成的会话亲和性 Cookie 时,只要会话亲和性 Cookie 仍然有效,负载均衡器就会将这些请求定向到同一后端实例或端点。为此,负载平衡器会将 Cookie 值映射到引用特定后端实例或端点的索引,并确保满足生成的 Cookie 会话亲和性要求。

如需使用生成的 Cookie 亲和性,请配置以下均衡模式和 localityLbPolicy 设置:

  • 对于后端实例组,请使用 RATE 均衡模式。
  • 对于后端服务的 localityLbPolicy,请使用 RING_HASHMAGLEV。如果您未明确设置 localityLbPolicy,负载均衡器会将 MAGLEV 用作隐式默认值。

如需了解详情,请参阅失去会话亲和性

如果您使用基于 HTTP Cookie 的亲和性 (HTTP_COOKIE),负载均衡器会在 Set-Cookie 标头中添加一个 HTTP Cookie,以响应初始 HTTP 请求。您可以指定 Cookie 的名称、路径和存留时间 (TTL)。

所有应用负载平衡器都支持基于 HTTP Cookie 的亲和性。

您可以使用以下后端服务参数和有效值来配置 Cookie 的 TTL 值(以秒、秒的分数 [以纳秒为单位] 或秒加秒的分数 [以纳秒为单位] 为单位):

  • consistentHash.httpCookie.ttl.seconds 可以设置为介于 0315576000000 之间(含边界值)的值。
  • consistentHash.httpCookie.ttl.nanos 可以设置为介于 0999999999 之间(含边界值)的值。由于单位是纳秒,因此 999999999 表示 .999999999 秒。

如果未指定 consistentHash.httpCookie.ttl.secondsconsistentHash.httpCookie.ttl.nanos,则改为使用 affinityCookieTtlSec 后端服务参数的值。如果未指定 affinityCookieTtlSec,则默认 TTL 值为 0

当客户端在 HTTP 请求的 Cookie 请求标头中包含 HTTP 会话亲和性 Cookie 时,只要会话亲和性 Cookie 仍然有效,负载均衡器就会将这些请求定向到同一后端实例或端点。为此,负载平衡器会将 Cookie 值映射到引用特定后端实例或端点的索引,并确保满足生成的 Cookie 会话亲和性要求。

如需使用 HTTP Cookie 亲和性,请配置以下均衡模式和 localityLbPolicy 设置:

  • 对于后端实例组,请使用 RATE 均衡模式。
  • 对于后端服务的 localityLbPolicy,请使用 RING_HASHMAGLEV。如果您未明确设置 localityLbPolicy,负载均衡器会将 MAGLEV 用作隐式默认值。

如需了解详情,请参阅失去会话亲和性

基于有状态 Cookie 的会话亲和性

如果您使用基于状态的 Cookie 亲和性 (STRONG_COOKIE_AFFINITY),负载平衡器会在 Set-Cookie 标头中添加 HTTP Cookie,以响应初始 HTTP 请求。您可以指定 Cookie 的名称、路径和存留时间 (TTL)。

以下负载均衡器支持基于状态的 Cookie 亲和性:

  • 区域外部应用负载均衡器
  • 区域级内部应用负载均衡器

您可以使用秒、秒的小数部分(以纳秒为单位)或秒与秒的小数部分(以纳秒为单位)来配置 Cookie 的 TTL 值。strongSessionAffinityCookie.ttl 所表示的时长不能设置为超过两周(1,209,600 秒)的值。

Cookie 的值通过对所选实例或端点进行编码来标识所选的后端实例或端点。只要 Cookie 有效,如果客户端在后续 HTTP 请求的 Cookie 请求标头中包含会话亲和性 Cookie,负载均衡器就会将这些请求定向到所选的后端实例或端点。

与其他会话亲和性方法不同:

  • 基于状态的基于 Cookie 的亲和性对均衡模式或负载均衡位置政策 (localityLbPolicy) 没有特定要求。

  • 当自动扩缩功能向托管式实例组添加新实例时,基于有状态 Cookie 的亲和性不会受到影响。

  • 当自动扩缩功能从托管式实例组中移除实例时,基于有状态 Cookie 的亲和性不会受到影响,除非移除的是所选实例。

  • 当自动修复功能从托管式实例组中移除实例时,基于有状态 Cookie 的亲和性不会受到影响,除非所选实例被移除。

如需了解详情,请参阅失去会话亲和性

基于 Cookie 的亲和性 TTL 为零的含义

所有基于 Cookie 的会话亲和性(例如生成的 Cookie 亲和性、HTTP Cookie 亲和性和基于有状态 Cookie 的亲和性)都具有 TTL 属性。

TTL 为零秒表示负载均衡器不会为 Cookie 分配 Expires 属性。在这种情况下,客户端会将该 Cookie 视为会话 Cookie。会话的定义因客户端而异:

  • 某些客户端(例如网络浏览器)会在整个浏览会话期间保留该 Cookie。这意味着,在应用关闭之前,Cookie 会在多个请求中保持不变。

  • 其他客户端将会话视为单个 HTTP 请求,并在之后立即舍弃 Cookie。

失去会话亲和性

所有会话亲和性选项都需要满足以下条件:

  • 所选后端实例或端点必须保持配置为后端。发生以下任一事件时,会话亲和性可能会被破坏:
    • 您从所选实例所属的实例组中移除该实例。
    • 托管式实例组自动扩缩或自动修复功能会从代管式实例组中移除所选实例。
    • 从相应 NEG 中移除所选端点。
    • 从后端服务中移除包含所选实例或端点的实例组或 NEG。
  • 所选后端实例或端点必须保持正常运行。如果所选实例或端点未通过健康检查,则会话亲和性可能就会被破坏。
  • 对于全球外部应用负载平衡器和传统应用负载平衡器,如果路由路径发生变化,后续请求或连接使用不同的第一层 Google Front End (GFE),则会话亲和性可能会中断。如果从互联网上的客户端到 Google 的路由路径在请求或连接之间发生变化,则系统可能会选择其他第一层 GFE。
除了基于有状态 Cookie 的会话亲和性之外,所有会话亲和性选项都具有以下额外要求:
  • 包含所选实例或端点的实例组或 NEG 不得处于其目标容量定义的已满状态。(对于区域托管式实例组,包含所选实例的实例组的可用区组件不得已满。)当实例组或 NEG 已满,而其他实例组或 NEG 未满时,会话亲和性可能会被破坏。由于使用 UTILIZATION 均衡模式时,满载情况可能会以不可预测的方式发生变化,因此您应使用 RATECONNECTION 均衡模式,以尽量减少会话亲和性被破坏的情况。

  • 已配置的后端实例或端点的总数必须保持不变。当发生以下事件中的至少一项时,已配置的后端实例或端点的数量会发生变化,并且会话亲和性可能会被破坏:

    • 添加新实例或端点:

      • 将实例添加到后端服务上的现有实例组。
      • 托管式实例组自动扩缩功能会向后端服务上的托管式实例组添加实例。
      • 您可以将端点添加到后端服务中的现有 NEG。
      • 您可以将非空实例组或 NEG 添加到后端服务。
    • 移除任何实例或端点,而不仅仅是所选的实例或端点

      • 您从实例组后端中移除了任何实例。
      • 托管式实例组自动扩缩或自动修复功能会从代管式实例组后端移除任何实例。
      • 您可以从 NEG 后端移除任何端点。
      • 从后端服务中移除所有现有的非空后端实例组或 NEG。
  • 运行状况良好的后端实例或端点的总数必须保持不变。当发生以下事件中的至少一项时,健康后端实例或端点的数量会发生变化,并且会话亲和性可能会被破坏:

    • 任何实例或端点通过了健康检查,从不健康状态转换为健康状态。
    • 任何实例或端点未通过健康检查,从健康状态转换为不健康状态或超时。