配置超时和截止时间

本文档介绍了如何为 Route Optimization API 请求配置超时和截止时间设置。未设置这些值或设置不正确可能会导致连接或回答质量问题。

您可以在请求正文中定义超时,在请求标头中定义截止时间。Route Optimization API 会在这些参数定义的时间限制内处理请求,并遵循最短时间值。

通过配置超时和截止时间,您可以通过以下方式管理处理时间:

  • 增加处理时间:
    • 解决高复杂度请求。
    • 获得更高质量的回答。
  • 缩短处理时间:
    • 以比默认模型更快的速度解决复杂度较低的请求。
    • 在更短的时间内解决请求,但获得的回答质量较低。

了解您的超时和截止时间需求

在配置超时和截止时间之前,请先查看本部分,以验证您是否了解端点和协议选择对这些设置的影响。

以下指南可帮助您确认是否使用了适合您目标的设置。

  • 对于持续和重复的请求,以及受益于更长求解时间的复杂请求,请使用非阻塞端点。
  • 对于小型请求和快速交付结果,请使用阻塞端点,接受质量权衡。
  • 在日常工作流中使用 gRPC,尤其是对于生产应用。
  • 使用 REST 进行测试、实验或一次性请求。

点击下面的按钮可查看图表,该图表可帮助您确定本文档的哪些部分与您的设置最相关。

在单独的标签页中打开图表

设置 timeout 参数

在请求正文中设置 timeout 参数的值,以指定服务器在返回响应之前处理请求的最长时间。如果 API 在达到分配的时间上限之前找到最佳解决方案,则实际花费的时间可能比分配的时间短。

使用时长协议缓冲区设置 timeout 参数,该参数是以秒为单位的时长,范围为 1 秒到 1800 秒。使用 allowLargeDeadlineDespiteInterruptionRisk 可将此值最多增加到 3600 秒。

下表根据请求复杂性以及配送和车辆数量列出了建议的 timeout 值。

配送和车辆数量 没有限制 时间窗口和负载限制宽松或路线较长 时间窗口紧迫、负载限制、复杂限制或路线过长
1 - 8 2 秒 2 秒 5 秒
9 - 32 5 秒 10 秒 20 秒
33 - 100 15 秒 30 秒 60 秒
101 - 1,000 45 秒 90 秒 180 秒
1,001 - 10,000 120 秒 360 秒 900s
10,001 人(含)以上 60 秒 + 120 秒/1 万次配送 每 1 万次配送中 360 度的次数 每 1 万次配送 900 秒

设置截止日期

在请求标头中设置截止时间,以定义 Route Optimization API 处理请求所用的时间上限。以下各小节介绍了如何为 REST 和 gRPC 请求设置截止时间。

REST 请求

使用 REST 调用阻塞端点时,您可以将截止时间延长至默认的 60 秒以上,因为对于复杂请求,默认时间通常太短。即使您已在请求正文中指定了更长的时限,也必须执行此操作,因为默认时限会覆盖请求正文中设置的任何大于 60 秒的 timeout 值。

通过设置 X-Server-Timeout 请求标头,将截止时间延长到默认的 60 秒以上。与请求正文不同,标头的值是秒数,但没有“s”后缀。您可以为此标头设置的最大值与 timeout 参数的限制一致。

以下代码示例展示了将 X-Server-Timeout 设置为 1800 秒的 HTTP 标头。

curl -X POST 'https://routeoptimization.googleapis.com/v1/projects/:optimizeTours' \
-H "Content-Type: application/json" \
-H "X-Server-Timeout: 1800" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
--data @- << EOM
{
  "model": {
    ...
  }
}
EOM

客户端库和 gRPC 请求

使用客户端库或 gRPC 时,您无需配置截止时间。使用这些方法时的默认截止时间为 3600 秒,即此 API 的最长请求时间。通过仅在请求正文中设置超时属性来配置求解时间。

影响超时和截止时间的参数

以下参数会影响超时和截止时间的运作方式:

  • 使用 allowLargeDeadlineDespiteInterruptionRisk 控制请求截止时限。
  • 定义搜索行为,使用 searchMode 平衡解决方案质量与延迟时间。

allowLargeDeadlineDespiteInterruptionRisk

allowLargeDeadlineDespiteInterruptionRisk 参数会将请求截止期限上限增加到 3,600 秒。如果未设置此参数,则超时和截止时间参数的最大值均为 1800 秒。

将 allowLargeDeadline DespiteInterruptionRisk 设置为 true,以将超时和截止时间参数的值增加到最多 3600 秒。

allowLargeDeadline DespiteInterruptionRisk 的允许值如下:

  • true:将超时和截止时间参数的最大值增加到 3600 秒,同时确认中断风险。
  • false(默认):将超时和截止时间参数的最大值保持为 1800 秒。

如果您认为自己需要超过 3600 秒的超时时间,请与您的 Google 代表联系。

searchMode

searchMode 参数控制优化器搜索解决方案的方式,让您可以优先考虑更快的响应(更低的延迟时间)或更高质量的解决方案。

如果您优先考虑提高解决方案质量,优化器会花费相当长的时间来寻找高质量的解决方案。对于这些较长的请求,请考虑设置更长的超时时间并使用非阻塞端点,以避免连接问题。

searchMode 的允许值如下:

  • SEARCH_MODE_UNSPECIFIED(默认):未指定的搜索模式,等同于 RETURN_FAST。
  • RETURN_FAST:在找到第一个理想解决方案后停止搜索。
  • CONSUME_ALL_AVAILABLE_TIME:花费所有可用时间来搜索更好的解决方案。如果 API 提前找到最佳解决方案,则不会使用所有可用时间。

启用 keepalive ping

当您向超时时间超过 60 秒的阻塞端点发出请求时,keepalive ping 有助于防止在等待响应时连接中断。Keepalive ping 是为保持连接活动以及检测和防止连接丢失而发送的小数据包。

根据您使用的 API 协议配置以下参数:

  • REST:在 TCP 连接级别配置 keepalive。
  • gRPC:在底层 TCP 套接字上或直接在 gRPC 协议中配置 keepalive ping。

以下部分介绍了如何为这两种协议设置 keepalive ping。

REST keepalive

使用 REST 时,如何配置 keepalive ping 取决于您的 HTTP 客户端库。客户端库和工具(例如 curl)可能会提供特定的配置选项或自动启用 ping。

如果您的库公开了底层 TCP 套接字,您可以使用 SO_KEEPALIVE 等选项直接在 TCP 套接字上配置 keepalive ping。为此,您可以使用 setsockopt() 等函数或其等效函数。

这个托管在 GitHub 上的函数演示了如何为 Python 内置 HTTP 客户端正确设置此功能。

如需详细了解 TCP 级 keepalive,请参阅 TLDP keepalive 概览或 HTTP 客户端库文档。

gRPC keepalive

gRPC 在协议中提供了自己的内置 keepalive 机制。如需了解如何使用客户端语言进行设置,请参阅 gRPC keepalive 指南。

包含 keepalive 的 gRPC 示例请求

以下示例展示了如何使用 Python 客户端库和 gRPC 级 keepalive ping 发出 optimizeTours 请求。

from google.maps import routeoptimization_v1 as ro
from google.maps.routeoptimization_v1.services.route_optimization.transports import grpc as grpc_transport
import sys

_REQUEST_TIMEOUT_SECONDS = 1800
_KEEPALIVE_PING_SECONDS = 30

def create_channel(*args, **kwargs):
  raw_options = kwargs.pop("options", ())
  options = dict(raw_options)
  options["grpc.keepalive_time_ms"] = _KEEPALIVE_PING_SECONDS * 1000
  options["grpc.keepalive_timeout_ms"] = 5000
  # Allow any number of pings between the request and the response.
  options["grpc.http2.max_pings_without_data"] = 0
  print(f"Using options: {options}", file=sys.stderr)
  return grpc_transport.RouteOptimizationGrpcTransport.create_channel(
      *args,
      options=list(options.items()),
      **kwargs,
  )

def create_grpc_transport(*args, **kwargs):
  if "channel" in kwargs:
    raise ValueError(
        "`channel` is overridden by this function, and must not be provided."
    )
  return grpc_transport.RouteOptimizationGrpcTransport(
      *args,
      channel=create_channel,
      **kwargs,
  )

def run_optimize_tours(request):
  client = ro.RouteOptimizationClient(transport=create_grpc_transport)
  return client.optimize_tours(request, timeout=_REQUEST_TIMEOUT_SECONDS)