为内部 HTTP(S) 负载平衡器设置流量管理

本指南包含为内部 HTTP(S) 负载平衡设置流量管理的示例。本文档展示了针对某些特定用例使用流量管理的示例。许多其他用例也是可行的。

准备工作

配置流量管理

您可以使用 Cloud Console、gcloud 或 Cloud Load Balancing API 配置流量管理。在所选的配置环境中,您可以使用 YAML 配置来设置流量管理。网址映射和后端服务都有自己的 YAML 文件。根据您所需的功能,您需要编写网址映射 YAML 和/或后端服务 YAML。

如果在编写这些 YAML 文件时需要帮助,您可使用以下资源:

访问 Cloud Console 中的 YAML 示例

如需访问 Cloud Console 中的 YAML 示例,请执行以下操作:

  1. 转到 Google Cloud Console 中的“负载平衡”页面。
    转到“负载平衡”页面
  2. HTTP(S) 负载平衡下,点击开始配置
  3. 选择“仅在我的虚拟机之间”。此设置表示负载平衡器是内部的。
  4. 点击继续
  5. 路由规则配置中,选择高级主机、路径和路由规则
  6. 点击添加主机和路径匹配器 (Add hosts and path matcher)。
  7. 点击代码指南链接。

您将看到路径匹配器 YAML 示例页面。

网址映射 YAML 示例

网址映射允许一个

单个服务

将所有流量发送到单个服务。请务必替换标有 [] 的变量:

defaultService: regions/[region]/backendServices/[backend-service1]
hostRules:
- hosts:
  - '*'
  pathMatcher: matcher1
name: [url-map-name]
pathMatchers:
- defaultService: regions/[region]/backendServices/[backend-service1]
  name: matcher1
  routeRules:
    - matchRules:
        - prefixMatch: /
      priority: [priority]
      routeAction:
        weightedBackendServices:
          - backendService: regions/[region]/backendServices/[backend-service1]
            weight: 100

拆分流量

在多个服务之间拆分流量。请务必替换标有 [] 的变量:

defaultService: regions/[region]/backendServices/[backend-service1]
hostRules:
- hosts:
  - '*'
  pathMatcher: matcher1
name: [url-map-name]
pathMatchers:
- defaultService: regions/[region]/backendServices/[backend-service1]
  name: matcher1
  routeRules:
  - matchRules:
    - prefixMatch: /prefix
    priority: 2
    routeAction:
      weightedBackendServices:
      - backendService: regions/[region]/backendServices/[backend-service1]
        weight: 95
      - backendService: regions/[region]/backendServices/[backend-service2]
        weight: 5

网址重定向

返回可配置的 3xx 响应代码。此外,系统还会使用适当的 URI 设置 Location 响应标头,并替换重定向操作中所指定的主机和路径。请务必替换标有 [] 的变量:

defaultService: regions/[region]/backendServices/[backend-service1]
kind: compute#urlMap
name: l7-ilb-map
region: region/[region]
hostRules:
- hosts:
  - '*'
  pathMatcher: matcher1
pathMatchers:
- defaultService: regions/[region]/backendServices/[backend-service1]
  name: matcher1
  routeRules:
    - matchRules:
        - prefixMatch: /
      priority: [priority]
      urlRedirect:
        hostRedirect: [REDIRECT_HOST]
        pathRedirect: [REDIRECT_PATH]
        redirectResponseCode: FOUND
        stripQuery: True

网址映射中允许多个网址

镜像流量

除了将请求转发到选定的后端服务,系统还会以“即发即弃”的方式将相同请求发送到配置的镜像后端服务。负载平衡器不会等待作为镜像请求发送目标的后端的响应。镜像有助于测试后端服务的新版本。此外,镜像还可用于调试后端服务调试版本的生产错误(而非生产版本的错误)。请务必替换标有 [] 的变量:

defaultService: regions/[region]/backendServices/[backend-service1]
kind: compute#urlMap
name: l7-ilb-map
region: region/[region]
hostRules:
- hosts:
  - '*'
  pathMatcher: matcher1
pathMatchers:
- defaultService: regions/[region]/backendServices/[backend-service1]
  name: matcher1
  routeRules:
    - matchRules:
        - prefixMatch: /
      priority: [priority]
      routeAction:
        weightedBackendServices:
          - backendService: regions/[region]/backendServices/[backend-service1]
            weight: 100
        requestMirrorPolicy:
          backendService: regions/[region]/backendServices/[backend-service2]

重写网址

在将请求发送到选定的后端服务之前,重写网址的主机名部分和/或网址的路径部分。请务必替换标有 [] 的变量:

defaultService: regions/[region]/backendServices/[backend-service1]
kind: compute#urlMap
name: l7-ilb-map
region: region/[region]
hostRules:
- hosts:
  - '*'
  pathMatcher: matcher1
pathMatchers:
- defaultService: regions/[region]/backendServices/[backend-service1]
  name: matcher1
  routeRules:
    - matchRules:
        - prefixMatch: /
      priority: [priority]
      routeAction:
        weightedBackendServices:
          - backendService: regions/[region]/backendServices/[backend-service1]
            weight: 100
        urlRewrite:
          hostRewrite: [REWRITE_HOST]
          pathPrefixRewrite: [REWRITE_PATH]

重试请求

配置负载平衡器重试失败请求的条件、负载平衡器在重试前等待的时间以及允许的最大重试次数。请务必替换标有 [] 的变量:

defaultService: regions/[region]/backendServices/[backend-service1]
kind: compute#urlMap
name: l7-ilb-map
region: region/[region]
hostRules:
- hosts:
  - '*'
  pathMatcher: matcher1
pathMatchers:
- defaultService: regions/[region]/backendServices/[backend-service1]
  name: matcher1
  routeRules:
    - matchRules:
        - prefixMatch: /
      priority: [priority]
      routeAction:
        weightedBackendServices:
          - backendService: regions/[region]/backendServices/[backend-service1]
            weight: 100
        retryPolicy:
          retryConditions: 502, 504
          numRetries: 3
          perTryTimeout:
            seconds: 1
            nanos: 50

超时

指定选定路由的超时时间。超时是根据从请求完全处理到响应完全处理的时间计算得出的。超时包括所有重试时间。请务必替换标有 [] 的变量:

defaultService: regions/[region]/backendServices/[backend-service1]
kind: compute#urlMap
name: l7-ilb-map
region: region/[region]
hostRules:
- hosts:
  - '*'
  pathMatcher: matcher1
pathMatchers:
- defaultService: regions/[region]/backendServices/[backend-service1]
  name: matcher1
  routeRules:
    - matchRules:
        - prefixMatch: /
      priority: [priority]
      routeAction:
        weightedBackendServices:
          - backendService: regions/[region]/backendServices/[backend-service1]
            weight: 100
        timeout:
          seconds: 30
          nanos: 100

错误

在处理请求时引入错误,以此模拟高延迟、服务过载、服务故障和网络分区等故障。在测试服务对模拟故障的弹性时,这项功能会非常有用。请务必替换标有 [] 的变量:

defaultService: regions/[region]/backendServices/[backend-service1]
kind: compute#urlMap
name: l7-ilb-map
region: region/[region]
hostRules:
- hosts:
  - '*'
  pathMatcher: matcher1
pathMatchers:
- defaultService: regions/[region]/backendServices/[backend-service1]
  name: matcher1
  routeRules:
    - matchRules:
        - prefixMatch: /
      priority: [priority]
      routeAction:
        weightedBackendServices:
          - backendService: regions/[region]/backendServices/[backend-service1]
            weight: 100
        faultInjectionPolicy:
          delay:
            fixedDelay:
              seconds: 10
              nanos: 20
            percentage: 25
          abort:
            httpStatus: 503
            percentage: 50

CORS

配置跨域资源共享 (CORS) 政策以处理有关执行 CORS 请求的内部 HTTP(S) 负载平衡设置。请务必替换标有 [] 的变量:

defaultService: regions/[region]/backendServices/[backend-service1]
kind: compute#urlMap
name: l7-ilb-map
region: region/[region]
hostRules:
- hosts:
  - '*'
  pathMatcher: matcher1
pathMatchers:
- defaultService: regions/[region]/backendServices/[backend-service1]
  name: matcher1
  routeRules:
    - matchRules:
        - prefixMatch: /
      priority: [priority]
      routeAction:
        weightedBackendServices:
          - backendService: regions/[region]/backendServices/[backend-service1]
            weight: 100
        corsPolicy:
            allowOrigins: my-domain.com
            allowMethods: GET, POST
            allowHeaders: Authorization, Content-Type
            maxAge: 1200
            allowCredentials: True

标头

在将请求发送到后端服务之前添加和移除请求标头。此外,在收到来自后端服务的响应后添加和移除响应标头。请务必替换标有 [] 的变量:

defaultService: regions/[region]/backendServices/[backend-service1]
kind: compute#urlMap
name: l7-ilb-map
region: region/[region]
hostRules:
- hosts:
  - '*'
  pathMatcher: matcher1
pathMatchers:
- defaultService: regions/[region]/backendServices/[backend-service1]
  name: matcher1
  routeRules:
    - matchRules:
        - prefixMatch: /
      priority: [priority]
      headerAction:
        requestHeadersToAdd:
          - headerName: header-1-name
            headerValue: header-1-value
            replace: True
        requestHeadersToRemove:
          - header-2-name
          - header-3-name
        responseHeadersToAdd:
          - headerName: header-4-name
            headerValue: header-4-value
            replace: True
        responseHeadersToRemove:
          - header-5-name
          - header-6-name

后端服务 YAML 示例

离群值检测

指定从 NEG 中逐出运行状况不佳的后端虚拟机或端点的条件,以及将后端或端点视为运行状况良好、足以再次接收流量的条件。请务必替换标有 [] 的变量:

kind: compute#backendService
loadBalancingScheme: INTERNAL_MANAGED
localityLbPolicy: RANDOM
name: regions/[region]/backendServices/[backend-service1]
outlierDetection:
  baseEjectionTime:
    nanos: 0
    seconds: '30'
  consecutiveErrors: 5
  consecutiveGatewayFailure: 3
  enforcingConsecutiveErrors: 2
  enforcingConsecutiveGatewayFailure: 100
  enforcingSuccessRate: 100
  interval:
    nanos: 0
    seconds: '1'
  maxEjectionPercent: 50
  successRateMinimumHosts: 5
  successRateRequestVolume: 100
  successRateStdevFactor: 1900
region: region/[region]

熔断

通过熔断功能,您可以设置失败阈值以防止客户端请求导致后端过载。在请求达到您设置的上限后,负载平衡器会停止批准新的连接或发送其他请求,从而为您的后端留出恢复时间。因此,熔断会通过向客户端返回错误而不是让后端过载来防止级联故障。这样一来,您便可处理一些流量,同时为管理过载情况提供时间,例如通过自动扩缩来增加容量以应对流量高峰。

设置每个连接的请求数上限以及到后端服务的连接数。此外,还要限制待处理请求数和重试次数。请务必替换标有 [] 的变量:

kind: compute#backendService
loadBalancingScheme: INTERNAL_MANAGED
localityLbPolicy: RANDOM
affinityCookieTtlSec: 0
backends:
- balancingMode: UTILIZATION
  capacityScaler: 1.0
  group: region/[region]/instanceGroups/[instance-group]
  maxUtilization: 0.8
circuitBreakers:
  maxConnections: 1000
  maxPendingRequests: 200
  maxRequests: 1000
  maxRequestsPerConnection: 100
  maxRetries: 3
connectionDraining:
  drainingTimeoutSec: 0
healthChecks:
- region/[region]/healthChecks/[health-check]

设置流量拆分

本示例演示了以下步骤:

  1. 为不同服务创建不同模板。

  2. 为这些模板创建实例组。

  3. 创建路由规则以设置 95%/5% 流量拆分比例。

  4. 发送 curl 命令,表明流量拆分百分比与配置大致匹配。

此处的说明假定您采用如下设置:

  • 地区为 us-west1
  • 已创建目标代理和转发规则以及名为 l7-ilb-map 的网址映射。
  • 转发规则的地址为 10.1.2.99

    请参阅为 Compute Engine 虚拟机设置内部 HTTP(S) 负载平衡中的说明。

  • 网址映射会将所有流量发送到一项名为 red-service 的后端服务,这是默认后端服务。

  • 将替代路径设置为分别向 blue-servicegreen-service 发送 5% 和 95% 的流量。

  • 使用了路径匹配器。

  • 您使用的是 Cloud Shell 或安装了 bash 的其他环境。

定义服务

以下 bash 函数可创建后端服务,包括实例模板和托管式实例组。

以下说明假定已创建 HTTP 运行状况检查 (l7-ilb-basic-check)。请参阅为 Compute Engine 虚拟机设置内部 HTTP(S) 负载平衡中的说明。

function make_service() {
  local name="$1"
  local region="$2"
  local zone="$3"
  local network="$4"
  local subnet="$5"
  local subdir="$6"

  www_dir="/var/www/html/$subdir"

  (set -x; \
  gcloud compute instance-templates create "${name}-template" \
    --region="$region" \
    --network="$network" \
    --subnet="$subnet" \
    --tags=allow-ssh,load-balanced-backend \
    --image-family=debian-9 \
    --image-project=debian-cloud \
    --metadata=startup-script="#! /bin/bash
  apt-get update
  apt-get install apache2 -y
  a2ensite default-ssl
  a2enmod ssl
  sudo mkdir -p $www_dir
  /bin/hostname | sudo tee ${www_dir}index.html
  systemctl restart apache2"; \
  gcloud compute instance-groups managed create \
    "${name}-instance-group" \
    --zone="$zone" \
    --size=2 \
    --template="${name}-template"; \
  gcloud compute backend-services create "${name}-service" \
    --load-balancing-scheme=INTERNAL_MANAGED \
    --protocol=HTTP \
    --health-checks=l7-ilb-basic-check \
    --health-checks-region="$region" \
    --region="$region"; \
  gcloud compute backend-services add-backend "${name}-service" \
    --balancing-mode='UTILIZATION' \
    --instance-group="${name}-instance-group" \
    --instance-group-zone="$zone" \
    --region="$region")
}

创建服务

现在调用该函数来创建三项服务,即 redgreenbluered 服务充当对 / 的请求的默认服务。greenblue 服务均在 /prefix 上设置,分别用于处理 95% 和 5% 的流量。

make_service red us-west1 us-west1-a lb-network backend-subnet ""
make_service green us-west1 us-west1-a lb-network backend-subnet /prefix
make_service blue us-west1 us-west1-a lb-network backend-subnet /prefix

创建网址映射

控制台

  1. 转到 Google Cloud Console 中的“负载平衡”页面。
    转到“负载平衡”页面
  2. 点击 l7-ilb-map 链接。
  3. 点击修改

配置新路由规则

  1. 路由规则下,选择高级主机、路径和路由规则
  2. 新主机和路径匹配器下,将服务设置为 red-service,以创建默认操作。
  3. 点击完成
  4. 点击添加主机和路径匹配器
  5. 主机字段中,输入 10.1.2.99。这是负载平衡器的转发规则的 IP 地址。
  6. 将以下 YAML 内容粘贴到路径匹配器框中,务必将 [PROJECT_ID] 替换为您的项目 ID:

    defaultService: https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-west1/backendServices/red-service
    name: matcher1
    routeRules:
    - priority: 2
      matchRules:
        - prefixMatch: /prefix
      routeAction:
        weightedBackendServices:
          - backendService: https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-west1/backendServices/green-service
            weight: 95
          - backendService: https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-west1/backendServices/blue-service
            weight: 5
    
  7. 点击完成

  8. 点击更新

gcloud

  1. 使用 gcloud compute url-maps export 命令导出现有网址映射:

    gcloud compute url-maps export l7-ilb-map \
      --destination=l7-ilb-map-config.yaml \
      --region=us-west1
    
  2. 将以下内容添加到 l7-ilb-map-config.yaml 网址映射文件末尾来更新此文件,务必将 [PROJECT_ID] 替换为您的项目 ID:

    hostRules:
    - hosts:
      - '*'
      pathMatcher: matcher1
    pathMatchers:
    - defaultService: https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-west1/backendServices/red-service
      name: matcher1
      routeRules:
      - priority: 2
        matchRules:
          - prefixMatch: /prefix
        routeAction:
          weightedBackendServices:
            - backendService: https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-west1/backendServices/green-service
              weight: 95
            - backendService: https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-west1/backendServices/blue-service
              weight: 5
    
  3. 使用 gcloud compute url-maps import 命令更新网址映射:

    gcloud compute url-maps import l7-ilb-map \
       --region=us-west1 \
       --source=l7-ilb-map-config.yaml
    

测试配置

如需测试配置,请先确保对 10.1.2.99/(先前设置的负载平衡器的 IP 地址)的请求会由默认 red 配置进行处理。

然后检查以确保发送到 10.1.2.99/prefix 的请求会按预期方式进行拆分。

创建客户端虚拟机

请参阅在区域中创建虚拟机实例以测试连接

将请求发送到 10.1.2.99

通过 SSH 连接到客户端。

gcloud compute ssh l7-ilb-client-us-west1-a \
    --zone=us-west1-a

运行以下命令:

for LB_IP in 10.1.2.99; do
    RESULTS=
    for i in {1..1000}; do RESULTS="$RESULTS:`curl ${LB_IP}`"; done >/dev/null 2>&1
    IFS=':'
    echo "***"
    echo "*** Results of load balancing to $LB_IP: "
    echo "***"
    for line in $RESULTS; do echo $line; done | grep -Ev "^$" | sort | uniq -c
    echo
done
检查结果
***
***Results of load balancing to 10.1.2.99:
***
502 red-instance-group-9jvq
498 red-instance-group-sww8

将请求发送到 10.1.2.99/prefix

将请求发送到 10.1.2.99/prefix 并注意流量拆分情况。

for LB_IP in 10.1.2.99; do
    RESULTS=
    for i in {1..1000}; do RESULTS="$RESULTS:`curl ${LB_IP}/prefix/index.html`"; done >/dev/null 2>&1
    IFS=':'
    echo "***"
    echo "*** Results of load balancing to $LB_IP/prefix: "
    echo "***"
    for line in $RESULTS; do echo $line; done | grep -Ev "^$" | sort | uniq -c
    echo
done
检查结果
***
***Results of load balancing to 10.1.2.99/prefix:
***
21 blue-instance-group-8n49
27 blue-instance-group-vlqc
476 green-instance-group-c0wv
476 green-instance-group-rmf4

Canary 设置会成功地将 95% 的 /prefix 请求发送到服务 green,并将 5% 的请求发送到服务 blue

通过流量控制,您可以根据提供的 Cookie 配置会话亲和性。如需为名为 red-service 的后端服务配置基于 HTTP_COOKIE 的会话亲和性,请按以下说明操作。

如需使用 HTTP_COOKIE 设置会话亲和性,请执行以下操作:

  1. 使用 gcloud compute backend_services export 命令获取后端服务配置。

    gcloud compute backend-services export red-service \
        --destination=red-service-config.yaml \
        --region=us-west1
    
  2. 按如下所示的方式更新 red-service-config.yaml 文件:

    sessionAffinity: 'HTTP_COOKIE'
    localityLbPolicy: 'RING_HASH'
    consistentHash:
     httpCookie:
      name: 'http_cookie'
      path: '/cookie_path'
      ttl:
        seconds: 100
        nanos: 30
     minimumRingSize: 10000
    
  3. red-service-config.yaml 文件中,删除以下行:

    sessionAffinity: NONE
    
  4. 更新后端服务配置文件:

    gcloud compute backend-services import red-service \
        --source=red-service-config.yaml \
        --region=us-west1
    

问题排查

如果流量未按照您配置的路由规则和流量政策进行路由,您可以根据以下信息来进行问题排查。

如需了解日志记录和监控功能,请参阅内部 HTTP(S) 日志记录和监控

症状:

  • 发往规则中所涉及服务的流量超过相关规则指定的流量。
  • 给定路由规则的 4xx 和 5xx HTTP 响应意外增加。

解决方案:检查路由规则的顺序。路由规则应按其被指定时的顺序进行解释。

网址映射中的路由规则按其被指定时的顺序进行解释。这不同于路径规则的解释方式,后者通过最长前缀匹配进行解释。对于路径规则,内部 HTTP(S) 负载平衡将仅选择单个路径规则;但是,如果您使用路由规则,它可能会应用多个路径规则。

定义路由规则时,请检查并确保列表顶部的规则不会意外路由原本会通过后续路由规则路由的流量。否则,收到被误发流量的服务可能会拒绝请求,而路由规则中涉及的服务将会收到较少的流量,甚或完全收不到流量。