使用 Cloud Scheduler 在 Compute Engine 上可靠地安排任务

在 Compute Engine 实例的网络等分布式系统中,可靠地安排任务充满挑战性,因为任何单个实例都可能因自动扩缩或网络分区而变得不可用。

通过使用 Cloud Scheduler 进行调度和使用 Pub/Sub 进行分布式消息传递,您可以构建一个应用,在一组 Compute Engine 实例中可靠地安排任务。如果您需要跨其他产品或云安排和编排复杂工作流,请考虑使用 Cloud Composer

本文包含以下三部分:

如何在 Compute Engine 上可靠地安排任务

Cron 是可在 Unix 系统上安排周期性任务的标准工具。由于您构建的系统会增加复杂性,并且是分布式的,运行 cron 的单台计算机可能成为一个关键的故障点。实例可能会因自动扩缩而停止运行,或者其网络分段可能与需要通信的系统分到不同的分区中。

Cloud Scheduler 是一项全托管式企业级服务,允许您安排事件。安排作业后,Cloud Scheduler 将调用已配置的事件处理程序,该程序可以是 App Engine 服务、HTTP 端点或 Pub/Sub 订阅。

如需在 Compute Engine 实例上运行任务以响应 Cloud Scheduler 事件,您需要将事件中继到这些实例。一种方法是调用在 Compute Engine 实例上运行的 HTTP 端点。另一种方法是使用 Pub/Sub 将消息从 Cloud Scheduler 传递到 Compute Engine 实例。此示例演示了第二种设计模式。

下图提供了此设计模式的架构概览。

架构概览图

在此实现中,您在 Cloud Scheduler 中安排事件,然后使用 Pub/Sub 将这些事件传输到 Compute Engine 实例。

Compute Engine 实例上的实用程序服务订阅 Pub/Sub 主题,并运行 Cron 作业以响应从这些主题中下拉的事件。由于该实用程序运行标准脚本,因此您无需修改当前的 Cron 脚本即可直接用于此示例。

通过使用 Pub/Sub 将任务安排逻辑与在 Compute Engine 上运行命令的逻辑分开,您无需更新 Cloud Scheduler 配置即可根据需要更新 Cron 脚本。您还可以更改任务计划,而无需更新 Compute Engine 实例上的实用程序服务。

配额

由于 Cron 作业数量通常很少,并且是按每小时、每周或每日的时间安排运行的,因此此设计模式不应超过 Cloud Scheduler 配额,该配额允许每分钟处理数十个请求,每天处理数千个请求。如果超出了配额,请考虑其他应用模式,如直接在应用代码中管理任务时间。

费用

如果您不将这些资源用于其他应用,则可以通过 Google Cloud 免费层级免费试用此设计模式的示例实现。如果您的免费配额被项目中的其他应用占用,则费用将由您对 Compute Engine、Cloud Scheduler 和 Pub/Sub 资源的使用总量决定。

Cloud Scheduler 的价格取决于安排的作业数量。Compute Engine 的价格取决于所用实例的类型和持续时间。Pub/Sub 的价格取决于所发送的数据量。

例如,如果在下一部分您运行一个小时的示例实现,然后删除 Google Cloud 资源,则费用大约为 1 美分。如需了解此估算值中费用的明细,并针对您自己的用例计算费用,请参阅价格计算器

设计模式的示例实现

您可在 GitHub 上找到此设计模式的示例实现,示例:在 Google Compute Engine 上可靠地安排任务

此示例由两部分组成:

  • 关于配置 Cloud Scheduler 和 Pub/Sub 的说明。

  • 在 Compute Engine 上运行的实用程序。该实用程序监控一个 Pub/Sub 主题。当检测到新消息时,它会在服务器上本地运行相应的命令。

示例随附的 readme 文件详细介绍了该示例,还介绍了如何在 Google Cloud 上运行该示例代码。

构建设计模式和示例

该示例演示了一种使用 Cloud Scheduler 为 Compute Engine 实现可靠调度解决方案的方法。这是一种很有用的设计模式,因为它将安排逻辑与在 Compute Engine 实例上运行命令的逻辑相分开,因此可以让您更改任务的位置和执行,而无需更新安排逻辑。

下图显示了此示例中的消息流。通过指定哪些实例可订阅指定主题,您可以控制 Cron 作业是在单个实例上还是多个实例上运行。

详细架构图

此架构的另一个优势是可让您控制 Cron 作业如何路由到实例。

您可以按照 Pub/Sub 主题 A 和 C 中所述,将不同的 Cron 消息发送给不同的服务器组。主题 A 中的任务发送给单个订阅者,而多个服务器订阅主题 C。您可以使用此策略在网络服务器上运行一组命令,在其他服务器上运行另一组命令。

另一个方案是在多台服务器中选择其一以运行命令。主题 B 举例说明了这一点。在这种情况下,多台服务器共享单个订阅,发布到主题 B 中的消息由第一台认领该消息的服务器处理,相应的命令仅在该服务器上运行。您可以利用该方法执行仅需在单台服务器上运行的夜间数据分析。

后续步骤

您可以修改该示例,将其作为自己的应用的模型。以下是一些帮助您开始使用的想法:

  • 更新 Cloud Scheduler 配置以指定您自己的 Cron 消息。您可以直接更新 Cron 作业,如创建和配置 Cron 作业中所述。

  • 更新 test_executor.py 以运行实际脚本而非 logger_sample_task.py,或者编写您自己的 Executor 实用程序。

  • 您无需在 Compute Engine 上手动启动实用程序并将其作为前台流程运行,只需将其作为系统守护程序或第三方工具(例如 systemdSupervisor)自动启动。

  • Cloud Scheduler 和 Pub/Sub 都不严格保证“恰好传输一次”。虽然概率很低,但也可能出现重复的消息传递。如果多次运行特定任务产生了不良结果,请使用分布式一致性锁定工具(如 Zookeeper)确保任务仅运行一次且仅由单个实例运行。

  • 安排任务时,请按照 Cron 最佳做法操作,并确保任务安排时间间隔足够长,以便任务在下次运行之前完成处理。

  • 考虑是否所有任务都需要运行 Compute Engine 实例。另一种方法是触发 Cloud Functions 以响应 Pub/Sub 消息。Cloud Functions 可以调用 Cloud API,但无法直接执行 Shell 脚本。如果您需要执行 Shell 脚本,可以调用 Compute Engine API 来创建临时 Compute Engine 实例以运行脚本。任务完成后,这些实例可以自行关闭。这可以让您在事件时间后灵活地完成任务,只需最少的费用。

试用其他 Google Cloud 功能。查阅我们的教程