1. 簡介

Eventarc 可輕鬆將 Cloud Run 服務連結至各種來源的事件。您可以在其中建構事件導向架構,讓微服務鬆耦合且分散。並為您處理事件擷取、傳送、安全防護、授權和錯誤處理工作。
Workflows 是全代管的自動化調度管理平台,可按照您定義的順序 (即工作流程) 執行服務。這些工作流程可以合併 Cloud Run 或 Cloud Functions 代管的服務、Cloud Vision AI 和 BigQuery 等 Google Cloud 服務,以及任何以 HTTP 為基礎的 API。
在本程式碼研究室中,您將建構微服務的事件驅動式協調流程,以處理圖片。您將使用 Workflows 協調 4 個圖片處理 Cloud Functions 的順序、輸入和輸出內容。接著,您將啟用自動化調度管理功能,透過 Eventarc 以鬆散耦合的方式回應 Cloud Storage 事件。
最後,您會獲得彈性但結構化的無伺服器架構,可處理圖片。

課程內容
- Eventarc 和 Workflows 總覽
- 如何部署 Cloud Functions 服務
- 如何使用 Workflows 自動化調度管理服務
- 如何使用 Eventarc 讓 Workflows 回應 Cloud Storage 事件
2. 設定和需求條件
自行設定環境
- 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶。



- 專案名稱是這個專案參與者的顯示名稱。這是 Google API 未使用的字元字串。你隨時可以更新。
- 專案 ID 在所有 Google Cloud 專案中都是不重複的,而且設定後即無法變更。Cloud 控制台會自動產生專屬字串,通常您不需要理會該字串。在大多數程式碼研究室中,您需要參照專案 ID (通常標示為
PROJECT_ID)。如果您不喜歡產生的 ID,可以產生另一個隨機 ID。你也可以嘗試使用自己的名稱,看看是否可用。完成這個步驟後就無法變更,且專案期間會維持不變。 - 請注意,有些 API 會使用第三個值,也就是「專案編號」。如要進一步瞭解這三種值,請參閱說明文件。
- 接著,您需要在 Cloud 控制台中啟用帳單,才能使用 Cloud 資源/API。完成這個程式碼研究室的費用不高,甚至可能完全免費。如要關閉資源,避免在本教學課程結束後繼續產生費用,您可以刪除建立的資源或專案。Google Cloud 新使用者可參加價值$300 美元的免費試用計畫。
啟動 Cloud Shell
雖然您可以透過筆電遠端操作 Google Cloud,但在本程式碼研究室中,您將使用 Google Cloud Shell,這是可在雲端執行的指令列環境。
在 Google Cloud 控制台中,點選右上角工具列的 Cloud Shell 圖示:

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

這部虛擬機器搭載各種您需要的開發工具,並提供永久的 5GB 主目錄,而且在 Google Cloud 運作,能大幅提升網路效能並強化驗證功能。您可以在瀏覽器中完成本程式碼研究室的所有作業。您不需要安裝任何軟體。
設定 gcloud
在 Cloud Shell 中,設定專案 ID 和要部署應用程式的區域。分別儲存為 PROJECT_ID 和 REGION 變數。如需可用區域,請參閱「Cloud Functions 區域」。
PROJECT_ID=your-project-id gcloud config set project $PROJECT_ID
取得原始碼
應用程式的原始碼位於 eventarc-samples 存放區的 processing-pipelines 資料夾中。
複製存放區:
git clone https://github.com/GoogleCloudPlatform/eventarc-samples.git
前往 eventarc-samples/processing-pipelines 資料夾:
cd eventarc-samples/processing-pipelines
3. 架構總覽
應用程式架構如下:

- 將圖片儲存至輸入 bucket,產生 Cloud Storage 建立事件。
- Eventarc 會透過 Cloud Storage 觸發條件讀取 Cloud Storage 建立事件,並以 CloudEvent 形式傳遞至 Workflows。
- 在工作流程的第一個步驟「篩選」中,Cloud Functions 服務會使用 Vision API 判斷圖片是否安全。如果圖片安全無虞,工作流程會繼續執行後續步驟。
- 在工作流程的第二個步驟中,Cloud Functions 服務「Labeler」會使用 Vision API 擷取圖片的標籤,並將標籤儲存至輸出 bucket。
- 在第三個步驟中,另一個 Cloud Functions 服務「Resizer」會使用 ImageSharp 調整圖片大小,並將調整後的圖片儲存至輸出 bucket。
- 最後一個步驟是 Watermarker,這是另一個 Cloud Functions 服務,會使用 ImageSharp 將 Labeler 的標籤浮水印新增至調整大小後的圖片,並將圖片儲存至輸出 bucket。
應用程式是由 Cloud Storage 事件觸發,因此屬於事件導向。圖片處理作業會在工作流程中進行,因此屬於協調作業。最終,這項服務會成為事件導向的自動化調度管理服務,以靈活但結構化的無伺服器架構處理圖片。
4. 建立 bucket
建立輸入 bucket,供使用者上傳圖片;建立輸出 bucket,供圖片處理管道儲存處理後的圖片。
在 Cloud Shell 中執行下列指令:
REGION=us-central1 BUCKET1=$PROJECT_ID-images-input-$RANDOM BUCKET2=$PROJECT_ID-images-output-$RANDOM gsutil mb -l $REGION gs://$BUCKET1 gsutil mb -l $REGION gs://$BUCKET2
5. 部署篩選器服務
首先部署第一個服務。這項 Cloud Functions 服務會接收 bucket 和檔案資訊,使用 Vision API 判斷圖片是否安全,然後傳回結果。
首先,請為 Cloud Functions 第 2 代和 Vision API 啟用必要服務:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ run.googleapis.com \ vision.googleapis.com
在頂層 processing-pipelines 資料夾中部署服務:
SERVICE_NAME=filter gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --entry-point Filter.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v3/filter/csharp
函式部署完畢後,請在變數中設定服務網址,稍後會用到:
FILTER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
6. 部署標籤服務
第二個 Cloud Functions 服務會接收 bucket 和檔案資訊,使用 Vision API 擷取圖片的標籤,並將標籤儲存至輸出 bucket。
在頂層 processing-pipelines 資料夾中部署服務:
SERVICE_NAME=labeler gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Labeler.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/labeler/csharp
函式部署完畢後,請在變數中設定服務網址,稍後會用到:
LABELER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
7. 部署調整大小服務
這項 Cloud Functions 服務會接收 bucket 和檔案資訊,使用 ImageSharp 調整圖片大小,然後將圖片儲存至輸出 bucket。
在頂層 processing-pipelines 資料夾中部署服務:
SERVICE_NAME=resizer gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Resizer.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/resizer/csharp \ --timeout=120s
請注意 2 分鐘的 timeout 值,讓調整大小函式有額外時間處理。
函式部署完畢後,請在變數中設定服務網址,稍後會用到:
RESIZER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
8. 部署浮水印服務
這項 Cloud Functions 服務會接收 bucket、檔案和標籤資訊,讀取檔案,使用 ImageSharp 將標籤新增為圖片浮水印,然後將圖片儲存至輸出 bucket。
在頂層 processing-pipelines 資料夾中部署服務:
SERVICE_NAME=watermarker gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Watermarker.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/watermarker/csharp
函式部署完畢後,請在變數中設定服務網址,稍後會用到:
WATERMARKER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
此時,所有四個 Cloud Functions 應已部署並執行:

9. 定義及部署工作流程
使用 Workflows 將篩選器、標籤人員、調整大小和浮水印服務整合至工作流程。Workflows 會按照我們定義的順序和參數,自動化調度管理這些服務的呼叫作業。
首先,請為 Workflows 啟用必要服務:
gcloud services enable \ workflows.googleapis.com \ workflowexecutions.googleapis.com
定義
工作流程會將 CloudEvent 做為參數。建立觸發條件後,Eventarc 會提供這項資訊。在前兩個步驟中,工作流程會記錄事件,並從事件中擷取儲存區和檔案資訊:
main:
params: [event]
steps:
- log_event:
call: sys.log
args:
text: ${event}
severity: INFO
- extract_bucket_and_file:
assign:
- bucket: ${event.data.bucket}
- file: ${event.data.name}
在 filter 步驟中,Workflows 會呼叫我們先前部署的篩選器服務。接著,系統會記錄並檢查檔案安全性:
- filter:
call: http.post
args:
url: FILTER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: filterResponse
- log_safety:
call: sys.log
args:
text: ${filterResponse.body.safe}
severity: INFO
- check_safety:
switch:
- condition: ${filterResponse.body.safe == true}
next: label
next: end
在 label 步驟中,Workflows 會呼叫標籤服務並擷取回應 (前 3 個標籤):
- label:
call: http.post
args:
url: LABELER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: labelResponse
在 resize 步驟中,Workflows 會呼叫調整大小服務並擷取回應 (調整大小後的圖片的 bucket 和檔案):
- resize:
call: http.post
args:
url: RESIZER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: resizeResponse
在 watermark 步驟中,工作流程會使用調整大小後的圖片和標籤呼叫浮水印服務,並擷取結果 (調整大小並加上浮水印的圖片):
- watermark:
call: http.post
args:
url: WATERMARKER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${resizeResponse.body.bucket}
file: ${resizeResponse.body.file}
labels: ${labelResponse.body.labels}
result: watermarkResponse
在 final 步驟中,Workflows 會從標籤器、調整大小器和浮水印服務傳回 HTTP 狀態碼:
- final:
return:
label: ${labelResponse.code}
resize: ${resizeResponse.code}
watermark: ${watermarkResponse.code}
部署
部署工作流程前,請務必手動或使用 sed,將服務網址替換為已部署函式的網址:
在頂層 processing-pipelines 資料夾中,前往 image-v3 資料夾 (workflows.yaml 檔案所在位置):
cd image-v3/
執行 sed,將預留位置網址替換為已部署服務的實際網址:
sed -i -e "s|FILTER_URL|${FILTER_URL}|" workflow.yaml
sed -i -e "s|LABELER_URL|${LABELER_URL}|" workflow.yaml
sed -i -e "s|RESIZER_URL|${RESIZER_URL}|" workflow.yaml
sed -i -e "s|WATERMARKER_URL|${WATERMARKER_URL}|" workflow.yaml
部署工作流程:
WORKFLOW_NAME=image-processing
gcloud workflows deploy $WORKFLOW_NAME \
--source=workflow.yaml \
--location=$REGION
幾秒後,您應該會在控制台中看到已部署的工作流程:

10. 建立觸發條件
工作流程部署完成後,最後一個步驟是透過 Eventarc 觸發條件,將工作流程連結至 Cloud Storage 事件。
一次性設定
首先,請為 Eventarc 啟用必要服務:
gcloud services enable \ eventarc.googleapis.com
建立要在 Eventarc 觸發條件中使用的服務帳戶。
SERVICE_ACCOUNT=eventarc-trigger-imageproc-sa gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Eventarc trigger image processing service account"
授予 workflows.invoker 角色,以便使用服務帳戶從 Eventarc 叫用 Workflows:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/workflows.invoker \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
將 eventarc.eventReceiver 角色指派給服務帳戶,以便在
Cloud Storage 觸發條件:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/eventarc.eventReceiver \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
將 pubsub.publisher 角色授予 Cloud Storage 服務帳戶。Eventarc 的 Cloud Storage 觸發條件需要這項設定:
STORAGE_SERVICE_ACCOUNT="$(gsutil kms serviceaccount -p $PROJECT_ID)"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:$STORAGE_SERVICE_ACCOUNT \
--role roles/pubsub.publisher
建立
執行下列指令來建立觸發條件。這個觸發條件會篩選輸入 Cloud Storage bucket 中的新檔案建立事件,並將這些事件傳遞至先前定義的工作流程:
TRIGGER_NAME=trigger-image-processing gcloud eventarc triggers create $TRIGGER_NAME \ --location=$REGION \ --destination-workflow=$WORKFLOW_NAME \ --destination-workflow-location=$REGION \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=$BUCKET1" \ --service-account=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
您可以在 Cloud 控制台的 Eventarc 部分看到觸發條件已建立並準備就緒:

11. 測試管道
圖片處理管道已準備好接收 Cloud Storage 中的事件。如要測試管道,請將圖片上傳至輸入 bucket:
gsutil cp beach.jpg gs://$BUCKET1
上傳圖片後,您應該會看到工作流程執行作業處於有效狀態:

大約一分鐘後,您應該會看到執行成功。您也可以查看工作流程的輸入和輸出內容:

列出輸出 bucket 的內容時,您應該會看到調整大小後的圖片、調整大小並加上浮水印的圖片,以及圖片的標籤:
gsutil ls gs://$BUCKET2 gs://$PROJECT_ID-images-output-$RANDOM/beach-400x400-watermark.jpeg gs://$PROJECT_ID-images-output-$RANDOM/beach-400x400.png gs://$PROJECT_ID-images-output-$RANDOM/beach-labels.txt
如要再次確認,可以開啟已調整大小並加上浮水印的圖片,查看結果:

12. 恭喜
恭喜,您已完成本程式碼研究室!
涵蓋內容
- Eventarc 和 Workflows 總覽
- 如何部署 Cloud Functions 服務
- 如何使用 Workflows 自動化調度管理服務
- 如何使用 Eventarc 讓 Workflows 回應 Cloud Storage 事件