配置队列路由、限制和重试

借助 Cloud Tasks,您可以通过定义队列级路由、分派速率限制和重试行为来管理任务执行。您可以在创建队列或更新现有队列时配置这些设置。

gcloud tasks queues create 和 gcloud tasks queues update 都使用相同的标志来设置队列参数,而 gcloud tasks queues update 还支持 --clear-* 标志,用于将参数重置为默认值。

在队列级别配置身份验证会覆盖任务级身份验证。如需了解详情,请参阅将 HTTP 目标任务与身份验证令牌搭配使用。

配置队列级路由

在队列级别配置路由会覆盖在任务级别设置的路由。 如果您想将 Cloud Tasks 用作目标服务前面的缓冲区,或者需要更改队列中所有任务的路由,此功能会非常有用。

队列级路由适用于:

  • 队列中的任务
  • 在设置队列级路由后添加到队列的任务

限制

队列级路由与 Cloud Key Management Service (Cloud KMS) 客户管理的加密密钥 (CMEK) 不兼容。如果启用了 CMEK,您将无法执行以下操作:

  • 在具有队列级路由的队列中创建任务
  • 应用队列级转送

为 HTTP 任务配置队列级路由

您可以在创建队列或更新队列时,将队列配置为替换任务级路由。如需配置队列级路由,请将队列的 uriOverride 参数设置为首选路由。默认情况下(uriOverrideEnforceMode 设置为 ALWAYS),队列级路由会覆盖任务级路由。您还可以将 uriOverrideEnforceMode 设置为 IF_NOT_EXISTS,以便仅在任务未指定自己的 URI 组件时应用队列级路由。

如果您要将队列级路由作为更新应用于现有队列,请在应用更改之前暂停队列,并在应用更改后等待一分钟再恢复队列。

  1. 通过运行以下命令暂停队列:

    gcloud tasks queues pause QUEUE_ID \
        --location=LOCATION

    替换以下内容:

    • QUEUE_ID:队列的 ID。
    • LOCATION:队列的位置。
  2. 更新或移除队列级路由。

    • 如需更新队列级路由,请将 uriOverride 参数设置为更新后的路由(或将 --http-uri-override 标志传递给 gcloud tasks queues update)。

    • 如需移除队列级路由,请执行以下操作:

      • Google Cloud CLI:运行带有 --clear-http-uri-override 标志的 gcloud tasks queues update:
      gcloud tasks queues update QUEUE_ID \
          --location=LOCATION \
          --clear-http-uri-override
      • REST API:使用空 JSON 对象 ({}) 为队列发送 patch 请求,并将 updateMask 查询参数设置为 httpTarget.uriOverride(或 httpTarget 以清除所有队列级 HTTP 目标设置)。

      • RPC API:为 Queue 发送 UpdateQueueRequest,其中指定了 queue.name,未设置 http_target.uri_override,并且 update_mask 参数设置为 http_target.uri_override(或 http_target 以清除所有队列级 HTTP 目标设置)。

    以下示例使用 REST API 更新任务路由到的主机:

    curl -X PATCH -d @- -i \
      -H "Authorization: Bearer ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      "https://cloudtasks.googleapis.com/v2/projects/PROJECT_ID/locations/LOCATION/queues/QUEUE_ID?updateMask=httpTarget.uriOverride" << EOF
    {
      "httpTarget": {"uriOverride":{"host":"NEW_HOST"}}
    }
    EOF
    

    替换以下内容:

    • ACCESS_TOKEN:您的访问令牌。您可以在终端中运行以下命令来获取此信息:

      gcloud auth application-default login
      gcloud auth application-default print-access-token
    • PROJECT_ID:您的 Google Cloud 项目的 ID。 您可以在终端中运行以下命令来获取此信息:

      gcloud config get-value project

    • LOCATION:队列的位置。

    • NEW_HOST:您希望队列路由到的新主机。

  3. 等待 1 分钟。

    新配置最长可能需要一分钟才能生效。等待恢复队列有助于防止任务使用旧配置进行分派。

  4. 运行以下命令,恢复队列:

    gcloud tasks queues resume QUEUE_ID \
        --location=LOCATION
  5. 通过运行以下命令,验证您的队列是否已成功配置:

    gcloud tasks queues describe QUEUE_ID \
        --location=LOCATION

    输出应包含您设置的 httpTarget 路由替换。

为 App Engine 任务配置队列级路由

如需为 App Engine 任务配置队列级路由,请将队列的 appEngineRoutingOverride 参数设置为首选 App Engine 服务和版本。

  1. 设置队列级路由并替换任何任务级路由:

    gcloud tasks queues update QUEUE_ID \
        --location=LOCATION \
        --routing-override=service:SERVICE,version:VERSION

    替换以下内容:

    • QUEUE_ID:队列 ID(其简称)。
    • LOCATION:队列的位置。
    • SERVICE:负责任务处理的 App Engine 工作器服务。
    • VERSION:应用版本。

    例如,如果您设置了一个工作器服务来处理队列中的所有任务,则可以路由到该服务和默认版本:

    gcloud tasks queues update QUEUE_ID \
        --location=LOCATION \
        --routing-override=service:SERVICE
  2. 运行以下命令,验证队列是否已成功配置:

    gcloud tasks queues describe QUEUE_ID \
        --location=LOCATION

    输出应类似如下所示:

    appEngineRoutingOverride:
      host: SERVICE.PROJECT_ID.appspot.com
      service: SERVICE
    name: projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID
    rateLimits:
      maxBurstSize: 100
      maxConcurrentDispatches: 1000
      maxDispatchesPerSecond: 500.0
    retryConfig:
      maxAttempts: 100
      maxBackoff: 3600s
      maxDoublings: 16
      minBackoff: 0.100s
    state: RUNNING
  3. 如需移除队列级路由,请运行以下命令:

    gcloud tasks queues update QUEUE_ID \
        --location=LOCATION \
        --clear-routing-override

    移除队列级路由后,系统会将任务级路由应用于队列中的任务以及未来添加到队列中的任务。

定义速率限制

速率限制决定了活跃队列可以分派任务的最大稳态速率,无论分派是首次任务尝试还是重试。

  1. 通过运行以下命令,设置队列可分派的并发任务的最大速率和数量:

    gcloud tasks queues update QUEUE_ID \
        --location=LOCATION \
        --max-dispatches-per-second=DISPATCH_RATE \
        --max-concurrent-dispatches=MAX_CONCURRENT_DISPATCHES

    替换以下内容:

    • QUEUE_ID:队列 ID(其简称)。
    • LOCATION:队列的位置。
    • DISPATCH_RATE:调度速率。这是存储桶中令牌的刷新速率。在任务流相对稳定的情况下,这相当于任务的分派速率。
    • MAX_CONCURRENT_DISPATCHES:队列中可同时运行的任务数上限。

    例如,如果您在创建队列时未设置任何参数,则可以通过运行以下命令来更新并发任务数上限:

    gcloud tasks queues update QUEUE_ID \
        --location=LOCATION \
        --max-concurrent-dispatches=MAX_CONCURRENT_DISPATCHES
  2. 运行以下命令,验证队列是否已成功配置:

    gcloud tasks queues describe QUEUE_ID \
        --location=LOCATION

    输出应类似如下所示:

    name: projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID
    rateLimits:
      maxBurstSize: 100
      maxConcurrentDispatches: MAX_CONCURRENT_DISPATCHES
      maxDispatchesPerSecond: DISPATCH_RATE
    retryConfig:
      maxAttempts: 100
      maxBackoff: 3600s
      maxDoublings: 16
      minBackoff: 0.100s
    state: RUNNING

定义队列处理速率的方法

您可以使用 Cloud Tasks API 或上传 queue.yaml 文件来定义队列处理速率。这两种方法都会生成使用相同底层机制的队列。

在这两种情况下,队列都使用令牌桶算法来控制任务执行的速率。每个命名队列都有一个用于存储令牌的令牌桶。

应用每执行一个任务,系统就会从令牌桶中移除一个令牌。队列会继续处理任务,直到其存储桶中的令牌用完为止。系统会根据您为队列指定的 max_dispatches_per_second 速率不断使用新令牌重新填充存储桶。如果队列包含要处理的任务,并且队列的存储桶包含令牌,则系统会同时处理与令牌数量相同的任务,最多可达到您设置的 max_concurrent_dispatches 值。

在已预热的活跃队列中,不均匀的负载可能会导致存储桶中的令牌数量显著增加,这可能会导致在突发请求到达时出现突发处理。在这种情况下,活跃队列的实际分派速率可能会暂时超过 max_dispatches_per_second 速率,从而消耗系统资源并与用户服务请求竞争。如果您使用队列根据下游服务的相对较慢的 SLA 来管理调度速率,则这些突发流量可能会导致 HTTP 429 (Too Many Requests) 或 HTTP 503 (Service Unavailable) 等错误。但是,如果队列是新创建的、最近恢复的或空闲了几分钟,则它会进入冷状态或空闲状态,并逐渐向 max_dispatches_per_second 增加,而不是立即突发。如需详细了解冷队列或空闲队列的预热,请参阅初始队列预热。

  • 使用任何 Cloud Tasks API 方法时,您都可以通过两个字段来定义队列分派速率:

    • max_dispatches_per_second
    • max_concurrent_dispatches

    第三个字段 max_burst_size 由系统根据您为 max_dispatches_per_second 设置的值计算得出。如需了解详情,请参阅 RateLimits 消息。

  • 使用 queue.yaml 方法时,您可以设置以下三个元素:

    • max_concurrent_requests,相当于 max_concurrent_dispatches
    • rate,等于 max_dispatches_per_second
    • bucket_size,等于 max_burst_size

在大多数情况下,使用 Cloud Tasks API 方法并让系统设置 max_burst_size 会产生非常高效的速率来管理突发请求。但在某些情况下,特别是当所需速率相对较慢时,使用 queue.yaml 方法手动将 bucket_size 设置为较小的值,或使用 Cloud Tasks API 将 max_concurrent_dispatches 设置为较小的值,可以为您提供更多控制。

设置重试参数

如果任务未成功完成,Cloud Tasks 会根据您设置的参数,使用指数退避算法重试该任务。任务成功执行后,系统会将其从队列中移除。在所有情况下,任务保留期限上限也适用。

(可选)您可以指定任务级重试配置,以替换任务的队列级重试配置。如需了解详情,请参阅为任务设置重试参数。

  1. 通过运行以下命令,指定队列中失败任务的重试次数上限,为重试尝试设置时间限制,并控制重试之间的时间间隔:

    gcloud tasks queues update QUEUE_ID \
        --location=LOCATION \
        --max-attempts=MAX_ATTEMPTS \
        --max-retry-duration=MAX_RETRY_DURATION \
        --min-backoff=MIN_INTERVAL \
        --max-backoff=MAX_INTERVAL \
        --max-doublings=MAX_DOUBLINGS

    替换以下内容:

    • QUEUE_ID:队列 ID(其简称)。
    • LOCATION:队列的位置。
    • MAX_ATTEMPTS:任务尝试次数上限,包括首次尝试。如需允许无限次重试,请将此值设置为 -1。 即使达到 MAX_ATTEMPTS 或将其设置为 -1,MAX_RETRY_DURATION 仍然适用。
    • MAX_RETRY_DURATION:重试失败任务的最长时间,从首次尝试任务开始计算。该值必须是以“s”结尾的字符串,例如 5s。如需指定无限时长,请将其设置为 0s。即使达到 MAX_RETRY_DURATION 或将其设置为 0s,MAX_ATTEMPTS 仍然适用。
    • MIN_INTERVAL:重试尝试之间等待的最短时间。该值必须是以“s”结尾的字符串,例如 5s。
    • MAX_INTERVAL:重试之间等待的最长时间。该值必须是以“s”结尾的字符串,例如 5s。
    • MAX_DOUBLINGS:在增加量变为常量之前,失败任务重试之间的时间间隔将加倍的最大次数。任务的重试间隔从 MIN_INTERVAL 开始,然后加倍 MAX_DOUBLINGS 次,然后线性增加,最后以 MAX_INTERVAL 的间隔重试,最多重试 MAX_ATTEMPTS 次。

      例如,如果 MIN_INTERVAL 为 10s,MAX_INTERVAL 为 300s,MAX_DOUBLINGS 为 3,则重试间隔会加倍 3 次,线性增加 2^3 * 10 秒,然后以 MAX_INTERVAL 的间隔重试,直到任务尝试了 MAX_ATTEMPTS 次:10 秒、20 秒、40 秒、80 秒、160 秒、240 秒、300 秒、300 秒,以此类推。

如需了解更多参数详情,请参阅 RetryConfig 资源参考文档。

  1. 运行以下命令,验证队列是否已成功配置:

    gcloud tasks queues describe QUEUE_ID \
        --location=LOCATION

    输出应包含您设置的 retryConfig 参数:

    retryConfig:
      maxAttempts: MAX_ATTEMPTS
      maxBackoff: MAX_INTERVAL
      maxDoublings: MAX_DOUBLINGS
      maxRetryDuration: MAX_RETRY_DURATION
      minBackoff: MIN_INTERVAL

后续步骤