1. 總覽
在先前的實驗室中,您建構了 Pic-a-daily 應用程式的事件驅動版本,該版本使用 Google Cloud Storage 觸發的 Cloud Function 執行 Image Analysis 服務、透過 Pub/Sub 執行 GCS 觸發的 Cloud Run 容器執行 Thumbnail 服務,並使用 Eventarc 觸發 Cloud Run 上的 Image Garbage Collector 服務。此外,Cloud Scheduler 也觸發了 Collage 服務:

在本實驗室中,您將建立應用程式的自動化調度管理版本。您不會讓不同類型的事件流經系統,而是使用 Workflows 自動化調度管理及呼叫服務,如下所示:

課程內容
- App Engine
- Cloud Firestore
- Cloud Functions
- Cloud Run
- 工作流程
2. 設定和需求
自修實驗室環境設定



請記住專案 ID,這是所有 Google Cloud 專案中不重複的名稱 (上述名稱已遭占用,因此不適用於您,抱歉!)。本程式碼研究室稍後會將其稱為 PROJECT_ID。
- 接著,您必須在 Cloud 控制台中啟用帳單,才能使用 Google Cloud 資源。
完成本程式碼研究室的費用應該不高,甚至完全免費。請務必按照「清除」部分的指示操作,瞭解如何停用資源,避免在本教學課程結束後繼續產生帳單費用。Google Cloud 新使用者可參加價值$300 美元的免費試用計畫。
啟動 Cloud Shell
雖然可以透過筆電遠端操作 Google Cloud,但在本程式碼研究室中,您將使用 Google Cloud Shell,這是可在雲端執行的指令列環境。
在 GCP 主控台,按一下右上角工具列的 Cloud Shell 圖示:

佈建並連線至環境的作業需要一些時間才能完成。完成後,您應該會看到如下的內容:

這部虛擬機器搭載各種您需要的開發工具,並提供永久的 5GB 主目錄,而且可在 Google Cloud 運作,大幅提升網路效能並強化驗證功能。本實驗室的所有工作都可在瀏覽器上完成。
3. Workflows 簡介

您可以使用 Workflows 建立無伺服器工作流程,按照您定義的順序,將一系列無伺服器工作串連在一起。您可以結合 Google Cloud API、Cloud Functions 和 Cloud Run 等無伺服器產品,並呼叫外部 API,藉此建構彈性的無伺服器應用程式。
正如您對協調器的期望,您可以使用 YAML/JSON 型工作流程定義語言,在 Workflows 中定義業務邏輯流程,並透過 Workflows Execution API 和 Workflows UI 觸發這些流程。
除了協調工具,還內建下列可設定功能:
- 在步驟之間彈性重試及處理錯誤,確保步驟可靠執行。
- JSON 剖析和步驟間的變數傳遞,可避免使用膠合程式碼。
- 決策的運算式公式可執行條件式步驟。
- 子工作流程,適用於模組化和可重複使用的工作流程。
- 支援外部服務,可自動調度管理 Google Cloud 以外的服務。
- 支援 Google Cloud 和外部服務的驗證,確保步驟執行安全無虞。
- 連接器可連線至 Pub/Sub、Firestore、Tasks、Secret Manager 等 Google Cloud 服務,方便整合。
更不用說,Workflows 是全代管的無伺服器產品。不必設定或擴充伺服器,而且只需要為實際使用的資源付費。
4. 啟用 API
在本實驗室中,您將使用 Workflows 連結 Cloud Functions 和 Cloud Run 服務。您也會使用 App Engine、Cloud Build、Vision API 和其他服務。
在 Cloud Shell 中,確認已啟用所有必要服務:
gcloud services enable \ appengine.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ compute.googleapis.com \ firestore.googleapis.com \ run.googleapis.com \ vision.googleapis.com \ workflows.googleapis.com \
過一段時間後,您應該會看到作業順利完成:
Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.
5. 取得程式碼
如果您尚未在先前的程式碼研究室中取得程式碼,請執行下列操作:
git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop
您會看到下列資料夾結構,與本實驗室相關:
frontend | workflows | ├── functions ├── |── trigger-workflow ├── |── vision-data-transform ├── services ├── |── collage ├── |── thumbnails ├── workflows.yaml
相關資料夾如下:
frontend包含我們在實驗室 4 中重複使用的 App Engine 前端。functions包含為工作流程建立的 Cloud Functions。services包含為工作流程修改的 Cloud Run 服務。workflows.yaml是工作流程定義檔案。
6. 探索 Workflows YAML
workflows.yaml 會以一系列步驟定義工作流程。讓我們一起瞭解。
工作流程開始時,會傳入一些參數。這兩項函式會觸發工作流程,並傳遞這些值。我們稍後會介紹這些函式,但這就是工作流程的啟動方式:

在 YAML 中,您可以看到這些參數已指派給 init 步驟中的變數,例如觸發事件的檔案和值區名稱,以及 Workflows 將呼叫的部分 Cloud Functions 和 Cloud Run 服務的網址:
main:
params: [args]
steps:
- init:
assign:
- file: ${args.file}
- bucket: ${args.bucket}
- gsUri: ${"gs://" + bucket + "/" + file}
- projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
- urls: ${args.urls}
接著,工作流程會檢查事件類型。支援的事件類型有 2 種:object.finalize (在雲端儲存空間 bucket 中儲存檔案時發出) 和 object.delete (刪除檔案時發出)。否則會引發不支援事件的例外狀況。

以下是 YAML 工作流程定義中的步驟,我們會檢查檔案儲存空間事件的類型:
- eventTypeSwitch:
switch:
- condition: ${args.eventType == "google.storage.object.finalize"}
next: imageAnalysisCall
- condition: ${args.eventType == "google.storage.object.delete"}
next: pictureGarbageCollectionGCS
- eventTypeNotSupported:
raise: ${"eventType " + args.eventType + " is not supported"}
next: end
請注意,工作流程支援 switch 陳述式和例外狀況處理,包括 switch 指令及其各種條件,以及在無法辨識事件時引發錯誤的 raise 指令。
接著來看看 imageAnalysisCall。這是 Workflows 的一系列呼叫,可呼叫 Vision API 分析圖片、轉換 Vision API 回應資料,以便排序圖片中辨識到的事物標籤、挑選主要顏色、檢查圖片是否適合顯示,然後將中繼資料儲存至 Cloud Firestore。
請注意,除了 Vision Transform Cloud Functions (稍後會部署),所有作業都會在 Workflows 中完成:

YAML 中的步驟如下所示:
- imageAnalysisCall:
call: http.post
args:
url: https://vision.googleapis.com/v1/images:annotate
headers:
Content-Type: application/json
auth:
type: OAuth2
body:
requests:
- image:
source:
gcsImageUri: ${gsUri}
features:
- type: LABEL_DETECTION
- type: SAFE_SEARCH_DETECTION
- type: IMAGE_PROPERTIES
result: imageAnalysisResponse
- transformImageAnalysisData:
call: http.post
args:
url: ${urls.VISION_DATA_TRANSFORM_URL}
auth:
type: OIDC
body: ${imageAnalysisResponse.body}
result: imageMetadata
- checkSafety:
switch:
- condition: ${imageMetadata.body.safe == true}
next: storeMetadata
next: end
- storeMetadata:
call: http.request
args:
url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file + "?updateMask.fieldPaths=color&updateMask.fieldPaths=labels&updateMask.fieldPaths=created"}
auth:
type: OAuth2
method: PATCH
body:
name: ${"projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
fields:
color:
stringValue: ${imageMetadata.body.color}
created:
timestampValue: ${imageMetadata.body.created}
labels:
arrayValue:
values: ${imageMetadata.body.labels}
result: storeMetadataResponse
分析完圖片後,接下來的兩個步驟是建立圖片的縮圖,以及最近圖片的拼貼。方法是部署 2 項 Cloud Run 服務,並從 thumbnailCall 和 collageCall 步驟呼叫這些服務:

YAML 中的步驟:
- thumbnailCall:
call: http.post
args:
url: ${urls.THUMBNAILS_URL}
auth:
type: OIDC
body:
gcsImageUri: ${gsUri}
result: thumbnailResponse
- collageCall:
call: http.get
args:
url: ${urls.COLLAGE_URL}
auth:
type: OIDC
result: collageResponse
這個執行分支會在 finalizeCompleted 步驟中,從各項服務傳回狀態碼,藉此結束:
- finalizeCompleted:
return:
imageAnalysis: ${imageAnalysisResponse.code}
storeMetadata: ${storeMetadataResponse.code}
thumbnail: ${thumbnailResponse.code}
collage: ${collageResponse.code}
另一種執行分支是從主要儲存空間 bucket 刪除檔案,其中包含圖片的高畫質版本。在這個分支中,我們要刪除含有縮圖的值區中的圖片縮圖,並從 Firestore 刪除其中繼資料。這兩項作業都是透過 Workflows 的 HTTP 呼叫完成:

YAML 中的步驟:
- pictureGarbageCollectionGCS:
try:
call: http.request
args:
url: ${"https://storage.googleapis.com/storage/v1/b/thumbnails-" + projectId + "/o/" + file}
auth:
type: OAuth2
method: DELETE
result: gcsDeletionResult
except:
as: e
steps:
- dummyResultInOutVar:
assign:
- gcsDeletionResult:
code: 200
body: "Workaround for empty body response"
- pictureGarbageCollectionFirestore:
call: http.request
args:
url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
auth:
type: OAuth2
method: DELETE
result: firestoreDeletionResult
刪除分支會傳回每個步驟的結果 / 程式碼,藉此結束:
- deleteCompleted:
return:
gcsDeletion: ${gcsDeletionResult}
firestoreDeletion: ${firestoreDeletionResult.code}
在後續步驟中,我們會建立 Workflows 的所有外部依附元件:buckets、Cloud Functions、Cloud Run 服務和 Firestore 資料庫。
7. 建立 bucket
您需要 2 個圖片儲存空間:1 個用於儲存原始高解析度圖片,另 1 個用於儲存圖片縮圖。
使用 gsutil 工具建立公開區域 (本例為歐洲) bucket,讓使用者能以一致的存取權上傳圖片:
export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_PICTURES}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_PICTURES}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_PICTURES}
建立另一個公開區域 bucket 來儲存縮圖:
export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_THUMBNAILS}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_THUMBNAILS}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_THUMBNAILS}
如要確認 bucket 已建立並設為公開,請前往 Cloud 控制台的 Cloud Storage 專區:

8. Vision 資料轉換 (Cloud Function)
Workflows.yaml 以 init、eventTypeSwitch、eventTypeNotSupported 步驟開頭。這些規則可確保來自值區的事件會傳送至正確步驟。
對於 object.finalize 事件,imageAnalysisCall 步驟會呼叫 Vision API,擷取所建立圖片的中繼資料。所有步驟都在 Workflows 中完成:

接著,我們需要轉換 Vision API 傳回的資料,才能將資料儲存至 Firestore。具體來說,我們需要:
- 列出圖片傳回的標籤。
- 擷取圖片的主色。
- 判斷圖片是否安全。
這項作業是在 Cloud Functions 的程式碼中完成,而 Workflows 只需呼叫這個函式:

探索程式碼
系統會呼叫 Cloud Functions vision-data-transform。您可以在 index.js 中查看完整程式碼。如您所見,這個函式的唯一用途是執行 JSON 到 JSON 的轉換,以便在 Firestore 中方便地儲存圖片中繼資料。
部署至 Cloud Functions
前往下列資料夾:
cd workflows/functions/vision-data-transform/nodejs
設定所選區域:
export REGION=europe-west1
gcloud config set functions/region ${REGION}
使用下列指令部署函式:
export SERVICE_NAME=vision-data-transform
gcloud functions deploy ${SERVICE_NAME} \
--source=. \
--runtime nodejs10 \
--entry-point=vision_data_transform \
--trigger-http \
--allow-unauthenticated
部署函式後,Workflows transformImageAnalysisData 步驟就能呼叫這個函式,進行 Vision API 資料轉換。
9. 準備資料庫
工作流程的下一個步驟是檢查圖片資料的安全性,然後將 Vision API 傳回的圖片相關資訊儲存到 Cloud Firestore 資料庫。這個資料庫是快速、全代管、無伺服器的雲端原生 NoSQL 文件資料庫:

這兩項作業都會在 Workflows 中完成,但您必須建立 Firestore 資料庫,才能儲存中繼資料。
首先,請在要建立 Firestore 資料庫的地區中建立 App Engine 應用程式 (這是 Firestore 的必要條件):
export REGION_FIRESTORE=europe-west2
gcloud app create --region=${REGION_FIRESTORE}
接著,在相同區域中建立 Firestore 資料庫:
gcloud firestore databases create --region=${REGION_FIRESTORE}
系統會以程式輔助方式在集合中建立文件,並包含 4 個欄位:
- name (字串):上傳圖片的檔案名稱,也是文件的鍵
- 標籤 (字串陣列):Vision API 辨識項目的標籤
- color (字串):主色的十六進位顏色代碼 (即 #ab12ef)
- created (日期):儲存這張圖片中繼資料的時間戳記
- 縮圖 (布林值):選用欄位,如果系統已為這張相片產生縮圖,這個欄位就會存在並設為 true
由於我們會在 Firestore 中搜尋有縮圖的圖片,並依建立日期排序,因此需要建立搜尋索引。您可以使用下列指令建立索引:
gcloud firestore indexes composite create --collection-group=pictures \ --field-config field-path=thumbnail,order=descending \ --field-config field-path=created,order=descending
請注意,建立索引最多可能需要 10 分鐘。
建立索引後,您可以在 Cloud 控制台中查看:

Workflows storeMetadata 步驟現在可以將圖片中繼資料儲存至 Firestore。
10. 縮圖服務 (Cloud Run)
鏈結中的下一個步驟是建立圖片的縮圖。這項作業是在 Cloud Run 服務的程式碼中完成,而 Workflows 會在 thumbnailCall 步驟中呼叫這項服務:

探索程式碼
Cloud Run 服務稱為「thumbnails」。您可以在 index.js 中查看完整程式碼。
建構及發布容器映像檔
Cloud Run 會執行容器,但您必須先建構容器映像檔 (定義於 Dockerfile 中)。您可以使用 Google Cloud Build 建構容器映像檔,然後將映像檔代管至 Google Container Registry。
前往下列資料夾:
cd workflows/services/thumbnails/nodejs
版本:
export SERVICE_SRC=thumbnails
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
. \
--tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
一兩分鐘後,建構作業應該就會成功,且容器會部署至 Google Container Registry。
部署至 Cloud Run
設定一些必要的變數和設定:
export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed
使用下列指令部署:
gcloud run deploy ${SERVICE_NAME} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
--no-allow-unauthenticated \
--memory=1Gi \
--update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}
服務部署完成後,Workflows thumbnailCall 步驟就能呼叫這項服務。
11. 相片組合服務 (Cloud Run)
接下來,請從最近的圖片製作拼貼。這項作業是在 Cloud Run 服務的程式碼中完成,而 Workflows 會在 collageCall 步驟中呼叫這項服務:

探索程式碼
Cloud Run 服務稱為「collage」。您可以在 index.js 中查看完整程式碼。
建構及發布容器映像檔
Cloud Run 會執行容器,但您必須先建構容器映像檔 (定義於 Dockerfile 中)。您可以使用 Google Cloud Build 建構容器映像檔,然後將映像檔代管至 Google Container Registry。
前往下列資料夾:
cd services/collage/nodejs
版本:
export SERVICE_SRC=collage
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
. \
--tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
一兩分鐘後,建構作業應該就會成功,且容器會部署至 Google Container Registry。
部署至 Cloud Run
設定一些必要的變數和設定:
export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed
部署:
gcloud run deploy ${SERVICE_NAME} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
--no-allow-unauthenticated \
--memory=1Gi \
--update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}
服務部署完畢後,您可以在 Cloud Console 的 Cloud Run 專區中,檢查這兩項服務是否正在執行,工作流程 collageCall 步驟也將能夠呼叫這項服務:

12. 部署工作流程
我們已部署 Workflows 的所有外部依附元件。其餘所有步驟 (finalizeCompleted、pictureGarbageCollectionGCS、pictureGarbageCollectionFirestore、deleteCompleted) 都可以由 Workflows 本身完成。
現在可以部署工作流程了!
前往內含 workflows.yaml 檔案的資料夾,然後使用下列指令部署該檔案:
export WORKFLOW_REGION=europe-west4
export WORKFLOW_NAME=picadaily-workflows
gcloud workflows deploy ${WORKFLOW_NAME} \
--source=workflows.yaml \
--location=${WORKFLOW_REGION}
幾秒後,工作流程就會部署完成,您可以在 Cloud Console 的「工作流程」部分中看到:

您可以點選工作流程並加以編輯。編輯時,您會看到工作流程的精美視覺化呈現方式:

您也可以透過 Cloud Console 手動執行工作流程,並提供正確的參數。我們會在下一個步驟中,因應 Cloud Storage 事件自動執行這項作業。
13. 工作流程觸發條件 (Cloud Functions)
工作流程已部署完成,現在,我們需要在 Cloud Storage bucket 中建立或刪除檔案時觸發 Workflows。這些分別是 storage.object.finalize 和 storage.object.delete 事件。
您可以使用 Workflows 的 API 和用戶端程式庫,建立、管理及執行 Workflows。在本例中,您將使用 Workflows Execution API,更具體來說,是使用其 Node.js 用戶端程式庫觸發工作流程。
您將透過監聽 Cloud Storage 事件的 Cloud Function 觸發 Workflows。由於 Cloud Function 只能監聽一種事件類型,因此您需要部署兩個 Cloud Function,分別監聽建立和刪除事件:

探索程式碼
系統會呼叫 Cloud Functions trigger-workflow。您可以在 index.js 中查看完整程式碼。
部署至 Cloud Functions
前往下列資料夾:
cd workflows/functions/trigger-workflow/nodejs
設定一些必要的變數和設定:
export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
export WORKFLOW_NAME=picadaily-workflows
export WORKFLOW_REGION=europe-west4
export COLLAGE_URL=$(gcloud run services describe collage-service --format 'value(status.url)')
export THUMBNAILS_URL=$(gcloud run services describe thumbnails-service --format 'value(status.url)')
export VISION_DATA_TRANSFORM_URL=$(gcloud functions describe vision-data-transform --format 'value(httpsTrigger.url)')
gcloud config set functions/region ${REGION}
部署函式,以回應最終事件:
export SERVICE_NAME=trigger-workflow-on-finalize
gcloud functions deploy ${SERVICE_NAME} \
--source=. \
--runtime nodejs10 \
--entry-point=trigger_workflow \
--trigger-resource=${BUCKET_PICTURES} \
--trigger-event=google.storage.object.finalize \
--allow-unauthenticated \
--set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}
部署第二個函式,回應刪除事件:
export SERVICE_NAME=trigger-workflow-on-delete
gcloud functions deploy ${SERVICE_NAME} \
--source=. \
--runtime nodejs10 \
--entry-point=trigger_workflow \
--trigger-resource=${BUCKET_PICTURES} \
--trigger-event=google.storage.object.delete \
--allow-unauthenticated \
--set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}
部署完成後,您可以在 Cloud 控制台中看到這兩個函式:

14. 前端 (App Engine)
在本步驟中,您將從 Pic-a-daily:實驗室 4 - 建立網頁前端,在 Google App Engine 上建立網頁前端,讓使用者從網頁應用程式上傳圖片,以及瀏覽上傳的圖片和縮圖。

如要進一步瞭解 App Engine 並閱讀程式碼說明,請參閱「Pic-a-daily:實驗室 4 - 建立網頁前端」。
探索程式碼
App Engine 應用程式稱為 frontend。您可以在 index.js 中查看完整程式碼。
部署至 App Engine
前往下列資料夾:
cd frontend
設定所選區域,並將 app.yaml 中的 GOOGLE_CLOUD_PROJECT 替換為實際專案 ID:
export REGION=europe-west1
gcloud config set compute/region ${REGION}
sed -i -e "s/GOOGLE_CLOUD_PROJECT/${GOOGLE_CLOUD_PROJECT}/" app.yaml
部署:
gcloud app deploy app.yaml -q
一兩分鐘後,系統會告知應用程式正在提供流量:
Beginning deployment of service [default]... ╔════════════════════════════════════════════════════════════╗ ╠═ Uploading 8 files to Google Cloud Storage ═╣ ╚════════════════════════════════════════════════════════════╝ File upload done. Updating service [default]...done. Setting traffic split for service [default]...done. Deployed service [default] to [https://GOOGLE_CLOUD_PROJECT.appspot.com] You can stream logs from the command line by running: $ gcloud app logs tail -s default To view your application in the web browser run: $ gcloud app browse
您也可以前往 Cloud Console 的 App Engine 專區,查看應用程式是否已部署,並探索 App Engine 的各項功能,例如版本控管和流量分配:

15. 測試工作流程
如要測試,請前往應用程式的預設 App Engine 網址 (https://<YOUR_PROJECT_ID>.appspot.com/),您應該會看到前端 UI 正在運作!

上傳圖片。這應該會觸發 Workflows,您可以在 Cloud Console 中看到工作流程執行作業處於 Active 狀態:

工作流程完成後,您可以按一下執行 ID,查看不同服務的輸出內容:

再上傳 3 張圖片。您也應該會看到 Cloud Storage bucket 和 App Engine 前端更新的圖片縮圖和拼貼:

16. 清除 (選用)
如果您不打算保留應用程式,可以刪除整個專案來清除資源,節省費用,並當個優質的雲端使用者:
gcloud projects delete ${GOOGLE_CLOUD_PROJECT}
17. 恭喜!
您使用 Workflows 調度及呼叫服務,建立了應用程式的自動化調度管理版本。
涵蓋內容
- App Engine
- Cloud Firestore
- Cloud Functions
- Cloud Run
- 工作流程