在 Compute Engine 上搭配 Cloud Scheduler 來進行穩定的工作排程

要在分散式系統 (例如 Compute Engine 執行個體網路) 中穩定地進行工作排程並不容易,這是由於任何個別的執行個體都可能會因為自動調度資源或網路分區而無法使用。

只要使用 Cloud Scheduler 來排程,並使用 Cloud Pub/Sub 進行分散式訊息傳遞,您就能建構應用程式,以便在大量的 Compute Engine 執行個體之間穩定地進行工作排程。如果您需要跨其他產品或雲端來進行排程和調度複雜的工作流程,請考慮改用 Cloud Composer

本文包含下列三個部分:

如何在 Compute Engine 上穩定地進行工作排程

Cron 是在 Unix 系統上進行週期性工作排程的標準工具。隨著建構的系統越來越複雜、越來越分散,只有一台電腦執行 Cron 可能就成為失敗的主因。執行個體可能會因為自動調度資源而停止,或是執行個體的網路區隔可能會與該執行個體需要通訊的系統分開。

Cloud Scheduler 提供全代管的企業級服務,能讓您用來進行事件排程。當您排定執行工作後,Cloud Scheduler 會呼叫已設定的事件處理常式,這個處理常式可能是 App Engine 服務、HTTP 端點,或是 Cloud Pub/Sub 訂閱項目。

如要在 Compute Engine 執行個體上執行工作來回應 Cloud Scheduler 事件,您必須將該事件轉發到那些執行個體。其中一種做法是呼叫在 Compute Engine 執行個體上執行的 HTTP 端點。而另一個選項則是使用 Cloud Pub/Sub,把訊息從 Cloud Scheduler 傳遞到 Compute Engine 執行個體。以下範例將說明第二個設計模式。

下圖提供這個設計模式的架構總覽。

架構總覽圖

在這個實作案例中,您在 Cloud Scheduler 中進行事件排程,然後利用 Cloud Pub/Sub 把這些事件傳送到 Compute Engine 執行個體。

Compute Engine 執行個體上的公用程式服務會訂閱 Cloud Pub/Sub 主題,並執行 Cron 工作來回應它從這些主題提取的事件。公用程式會執行標準指令碼;您不需要修改目前的 Cron 指令碼,就能在這個範例中使用。

只要使用 Cloud Pub/Sub 讓工作排程邏輯與在 Compute Engine 上執行指令的邏輯分離,您就能在不必更新 Cloud Scheduler 設定的情況下,視需要更新 Cron 指令碼。您也不必更新 Compute Engine 執行個體上的公用程式,就能變更工作排程。

配額

由於 Cron 工作通常並不多,且會按照每小時、每天或每週的排程來執行,因此這個設計模式應該不會超出 Cloud Scheduler 配額 (該配備允許每分鐘數十個要求,以及每天數千個要求)。如果該設計模式會超出配額,請考慮使用其他應用程式模式,例如直接在應用程式程式碼中管理工作時間。

費用

您可以利用 GCP 免費版,免費試用這個設計模式的實作範例,但您無法將這些資源用在其他應用程式上。如果您專案中的其他應用程式使用了您的免費配額,那麼費用將由您的 Compute Engine、Cloud Scheduler 及 Cloud Pub/Sub 總資源用量來決定。

Cloud Scheduler 是根據已排程工作數來計費的。而 Compute Engine 是根據已使用執行個體的類型和使用時間來計費的。Cloud Pub/Sub 則是根據已傳送資料量來計費。

舉例來說,如果您執行下一節的實作範例一小時,然後刪除 GCP 資源,那麼費用約為 1 美分。如需這個預估費用的細目,以及瞭解如何計算您使用案例的費用,請參閱 Pricing Calculator

設計模式的實作範例

GitHub 提供這個設計模式的實作範例:在 Compute Engine 上進行穩定的工作排程範例

範例包含兩個部分:

  • 設定 Cloud Scheduler 和 Cloud Pub/Sub 的操作說明。

  • 在 Compute Engine 上執行的公用程式。這個公用程式會監控 Cloud Pub/Sub 主題。當系統偵測到新訊息時,就會在伺服器上本機執行對應的指令。

範例隨附的 Readme 檔案提供更詳細的範例說明,以及在 GCP 上執行程式碼範例的方式。

如需依排程啟動及停止執行個體的具體案例,請參閱使用 Cloud Scheduler 為運算執行個體排程一文。

根據設計模式與範例進行建構

範例說明使用 Cloud Scheduler 服務來實作穩定的 Compute Engine 排程解決方案的一種方式。這是個實用的設計模式,因為它會讓排程邏輯與在 Compute Engine 執行個體上執行指令的邏輯分離,讓您不用更新排程邏輯,就能夠變更工作的位置與執行作業。

下圖顯示此範例中的訊息流程。只要指定要用哪個執行個體訂閱特定的主題,您就能控制 Cron 工作會在單一執行個體上執行,還是在多個執行個體上執行。

詳細的架構圖

這個架構的另一項優點,就是能夠控制 Cron 工作轉送到執行個體的方式。

您可以把不同的 Cron 訊息傳送到不同組的伺服器,如 Cloud Pub/Sub 主題 A 和 C 中所示。系統會把主題 A 中的工作會傳送給單一訂閱者,而主題 C 則有多個伺服器訂閱。您可以透過這項策略,在網路伺服器上執行一套指令,然後在其他伺服器上執行另一套指令。

另一種選擇是在多個伺服器中的其中一個伺服器上執行指令,如主題 B 所示。在這種情況下,會有多個伺服器共用一個訂閱,而發佈到主題 B 的訊息將會由第一個取得該訊息的伺服器來處理,且對應的指令只會在該伺服器上執行。您可以使用這個方法,來執行只需要在單一伺服器上執行的夜間資料分析。

後續步驟

您可以修改範例來做為自己應用程式的模型。以下是幾點能協助您開始進行的建議:

  • 更新 Cloud Scheduler 的設定來指定您自己的 Cron 訊息。您可以直接更新 Cron 工作,如建立並設定 Cron 工作一文中所述。

  • 更新 test_executor.py 來執行實際的指令碼,而不是執行 logger_sample_task.py,或是編寫您自己的 Executor 公用程式。

  • 您可以利用系統或第三方工具 (例如 systemdSupervisor),把公用程式當做 Daemon 來自動啟動,而非在 Compute Engine 上手動啟動公用程式,然後把它當做前景處理程序來執行。

  • Cloud Scheduler 和 Cloud Pub/Sub 都無法保證絕對只會傳送「一次」。甚至還可能發生重複傳送訊息的情況,雖然可能性不大。如果多次執行特定工作會產生您不想要的結果,請使用分散式穩定鎖定工具 (例如 Zookeeper),來確保工作只會由單一執行個體執行,且只會執行一次。

  • 當您進行工作排程時,請按照 Cron 最佳做法來操作,並確保工作的間隔時間長到足以讓工作在下次執行之前處理完畢。

  • 思考執行 Compute Engine 執行個體對所有工作來說是否都是必要的。替代方案針對 Cloud Pub/Sub 訊息來觸發 Cloud Functions。Cloud Functions 可以呼叫 Cloud APIs,但無法直接執行殼層指令碼。如果您需要執行殼層指令碼,您可以呼叫 Compute Engine API 來建立臨時的 Compute Engine 執行個體以執行指令碼。這些執行個體能夠在工作完成時自行關閉。這讓您擁有以最少的花費在事件發生後立即完成工作的彈性。

試用其他的 Google Cloud Platform 功能。請參考我們的教學課程