使用 Eventarc 和 Cloud Run 函式觸發 Cloud Storage 的事件處理

1. 總覽

在本研究室中,您將瞭解如何使用 Cloud Storage 值區事件和 Eventarc 觸發事件處理作業。您將使用 Cloud Run 函式分析資料和處理圖片。這個函式會使用 Google 的 Vision API,並將產生的圖片儲存在 Cloud Storage 值區中。

424779013ac38648.png

學習目標

如何建構圖像處理管道。

  • 設定 Storage 值區
  • 建立 Cloud Run 函式,讀取及寫入 Cloud Storage 中的物件
  • 部署 Eventarc 觸發條件
  • 整合 Vision API 以偵測食物圖片
  • 測試並驗證端對端解決方案

必要條件

  • 本實驗室假設您已熟悉 Cloud 控制台和殼層環境。
  • 具備 Cloud Storage、Cloud Run 函式或 Vision API 的使用經驗會有所幫助,但並非必要條件。

2. 設定和需求

Cloud 專案設定

  1. 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請務必建立帳戶

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • 「Project name」是這個專案參與者的顯示名稱。這是 Google API 不會使用的字元字串。您隨時可以更新。
  • 專案 ID 在所有 Google Cloud 專案中都是不重複的值,且無法變更 (設定後即無法變更)。Cloud 控制台會自動產生專屬字串,您通常不需要特別留意。在大多數程式碼研究室中,您都需要參照專案 ID (通常會以 PROJECT_ID 表示)。如果您不喜歡系統產生的 ID,可以隨機產生另一個 ID。或者,您也可以自行嘗試,看看是否可用。在這個步驟完成後就無法變更,且會在整個專案期間維持不變。
  • 提醒您,有些 API 會使用第三個值「專案編號」。如要進一步瞭解這三個值,請參閱說明文件
  1. 接下來,您需要在 Cloud 控制台中啟用帳單功能,才能使用 Cloud 資源/API。執行這個程式碼研究室不會產生太多費用,甚至可能完全不會產生費用。如要關閉資源,避免在本教學課程結束後繼續產生費用,您可以刪除建立的資源或專案。Google Cloud 新使用者可享有價值 $300 美元的免費試用期

啟用 Cloud Shell

按一下搜尋列右側的圖示,即可啟用 Cloud Shell。

b02c63d9c7632ef8.png

環境設定

  1. 在 Cloud Shell 終端機中執行下列指令,建立專案和資源相關的環境變數。
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NAME=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
export REGION=us-east1 
export UPLOAD_BUCKET_NAME=menu-item-uploads-$PROJECT_ID
export UPLOAD_BUCKET=gs://menu-item-uploads-$PROJECT_ID
export BUCKET_THUMBNAILS=gs://menu-item-thumbnails-$PROJECT_ID
export MENU_SERVICE_NAME=menu-service
export USER_EMAIL=$(gcloud config list account --format "value(core.account)")
  1. 啟用實驗室所需的 API
gcloud services enable \
    vision.googleapis.com \
    cloudfunctions.googleapis.com \
    pubsub.googleapis.com \
    cloudbuild.googleapis.com \
    logging.googleapis.com \
    eventarc.googleapis.com \
    artifactregistry.googleapis.com \
    run.googleapis.com \
    --quiet
  1. 複製存放區
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git && cd cymbal-eats/cloud-functions

3. 設定 Cloud Storage 值區

建立儲存空間值區

為圖片處理管道建立上傳和縮圖 Cloud Storage 值區。

使用 gsutil mb 指令與不重複的名稱建立兩個值區:

  1. 圖片會先上傳至哪個上傳值區
  2. 用來儲存產生的縮圖圖片的縮圖值區

建立值區來上傳新圖片:

gsutil mb -p $PROJECT_ID -l $REGION $UPLOAD_BUCKET

輸出內容範例:

Creating gs://menu-item-uploads-cymbal-eats-8399-3119/...

建立用來儲存產生的縮圖的值區:

gsutil mb -p $PROJECT_ID -l $REGION $BUCKET_THUMBNAILS

輸出內容範例:

Creating gs://menu-item-thumbnails-cymbal-eats-8399-3119/...

更新值區權限

更新儲存體值區權限,允許使用者讀取權限。

使用 gsutil iam ch 指令授予讀取及寫入值區中物件的權限:

gsutil iam ch allUsers:objectViewer $UPLOAD_BUCKET
gsutil iam ch allUsers:objectViewer $BUCKET_THUMBNAILS

輸出範例

Updated IAM policy for project [cymbal-eats-8399-3119].
[...]

4. 設定服務帳戶

為 Cloud 函式建立自訂服務帳戶,以便處理縮圖:

export CF_SERVICE_ACCOUNT=thumbnail-service-sa
gcloud iam service-accounts create ${CF_SERVICE_ACCOUNT}

授予 artifactregistry.reader 角色,允許從 Artifact Registry 執行讀取作業:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role "roles/artifactregistry.reader"

授予 storage.objectCreator 角色,允許將產生的圖片儲存在縮圖值區:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role "roles/storage.objectCreator"

授予 run.invoker 角色,允許叫用 Cloud Run 服務:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role "roles/run.invoker"

授予 eventarc.eventReceiver 角色,允許接收來自供應商的事件:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role "roles/eventarc.eventReceiver"

pubsub.publisher 角色授予 Cloud Storage 服務帳戶。這樣一來,服務帳戶就能在圖片上傳至值區時發布事件。

GCS_SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER)

gcloud projects add-iam-policy-binding $PROJECT_NUMBER \
    --member "serviceAccount:$GCS_SERVICE_ACCOUNT" \
    --role "roles/pubsub.publisher"

5. 圖片處理函式簡介

建立函式,從 Cloud Storage 下載圖片、調整圖片大小,然後將圖片上傳回 Cloud Storage。這個函式會呼叫 Vision API,為圖片指派說明標籤。這個函式會檢查說明標籤。如果標籤將圖片識別為「Food」,系統會將事件傳送至選單服務,以更新選單項目的圖片和縮圖。

4c3c3b758dba6a9f.png

觸發函式

Cloud Storage 函式會根據 Cloud Storage 的 Pub/Sub 通知運作,並支援類似的事件類型:

在本研究室中,您將在 Cloud Storage 中完成物件時部署及觸發函式。

物件建立完成

當 Cloud Storage 物件的「寫入」作業順利完成時,系統就會觸發物件完成事件。具體來說,這表示建立新物件或覆寫現有物件會觸發這個事件。這個觸發條件會忽略封存和中繼資料更新作業。

6. 整合 Cloud Storage

Cloud Storage 是在 Google Cloud 中為您儲存物件的服務。物件是不可變更的資料片段,由任何格式的檔案組成。物件會存放在名為值區的容器中。所有值區都與專案相關聯,您可以在機構底下為專案分組。用戶端程式庫API 可協助您整合 Cloud Storage

在本研究室中,您將使用用戶端程式庫讀取及寫入 Cloud Storage 中的物件。

安裝用戶端程式庫

Cloud 用戶端程式庫支援多種常見的程式設計語言。如要開始使用這些程式庫,您必須安裝用戶端程式庫

使用用戶端程式庫

實作細節大致取決於程式設計語言。如要在應用程式中使用用戶端程式庫,第一步是匯入 Cloud Storage 依附元件。舉例來說,在 Node.js 專案中,匯入項目會新增至 package.json 檔案。下列程式碼片段顯示本實驗室的 package.json 檔案通知。

package.json

{
    "name": "thumbnail-service",
    "version": "0.1.0",
    "dependencies": {
      "@google-cloud/functions-framework": "^3.0.0",
      "@google-cloud/storage": "^5.18.2",
      "@google-cloud/vision": "^2.4.2",
        ...
    }
  }

註冊 CloudEvent 回呼

使用 Functions Framework 註冊 CloudEvent 回呼,當新圖片上傳至值區時,Cloud Storage 會觸發這項回呼。

index.js

functions.cloudEvent('process-thumbnails', async (cloudEvent) => {
    console.log(`Event ID: ${cloudEvent.id}`);
    console.log(`Event Type: ${cloudEvent.type}`);
    ...

建立儲存空間參照物件

匯入用戶端程式庫後,您需要建立新的儲存空間用戶端和應用程式將要互動的儲存空間。

index.js

const storage = new Storage();
const bucket = storage.bucket(file.bucket);
const thumbBucket = storage.bucket(process.env.BUCKET_THUMBNAILS);

下載 Cloud Storage 物件

index.js

await bucket.file(file.name).download({
            destination: originalFile
        });

將物件上傳至 Cloud Storage

您可以透過三種方式將上傳要求傳送至 Cloud Storage:單一要求、可暫停或 XML API 多部分上傳。如果要上傳較大的檔案或串流上傳檔案,請使用支援續傳的上傳功能。使用 XML API 時,檔案會分成多個部分上傳,並組合為單一物件。對於較小的物件,請使用單一要求上傳。

以下程式碼會使用單一要求上傳功能,將圖片上傳至雲端儲存空間。

index.js

const thumbnailImage = await thumbBucket.upload(thumbFile);

7. 整合 Vision API

Cloud Vision 可讓開發人員輕鬆將視覺偵測功能整合至應用程式,包括為圖片加上標籤、臉部和地標偵測、光學字元辨識 (OCR),以及為煽情露骨內容加上標記。

安裝用戶端程式庫

Cloud 用戶端程式庫支援多種常見的程式設計語言。如要開始使用這些程式庫,您必須安裝用戶端程式庫

建立 Image Annotator 用戶端

如要使用官方用戶端 SDK 存取 Google API,您必須根據 API 的探索文件建立服務物件,該文件會向 SDK 說明 API。您必須使用憑證,從 Vision API 的探索服務擷取該資訊。

index.js

const client = new vision.ImageAnnotatorClient();

建構 Vision API 要求

Vision API 可在圖片檔案上執行功能偵測,方法是在要求主體中將圖片檔案內容傳送為 base64 編碼字串。

如要使用圖片資源建立要求,以便為圖片加上註解。對這個 API 提出的要求,會以含有要求清單的物件形式呈現。這份清單中的每個項目都包含兩種資訊:

  • Base64 編碼的圖片資料
  • 您想在圖片上加上註解的功能清單。

index.js

        const client = new vision.ImageAnnotatorClient();
        const visionRequest = {
            image: { source: { imageUri: `gs://${file.bucket}/${file.name}` } },
            features: [
                { type: 'LABEL_DETECTION' },
            ]
        };
        const visionPromise = client.annotateImage(visionRequest);

8. 部署 Cloud Run 函式

這項圖片大小調整服務是更大規模的 Cymbal Eats 系統的一部分。在本節中,您只會部署與圖像處理功能相關的元件。完整安裝程序整合了使用者介面,用於上傳圖片,以及用於儲存產生中繼資料的下游要求。這些功能並未在本實驗室中安裝。

系統會在函式部署期間建立下列元件:

  • Cloud Run 函式
  • Eventarc 觸發條件
  • Pub/Sub 主題和訂閱項目

在 Cloud Shell 終端機中執行下列指令,在 menu-item-uploads-$PROJECT_ID 上部署 Cloud Run 函式,並使用觸發值區:

如要直接將 Cloud Run 函式部署至 Cloud Run,請先部署函式,然後建立函式的觸發條件。

部署 Cloud Run 函式:

gcloud beta run deploy process-thumbnails \
      --source=thumbnail \
      --function process-thumbnails \
      --region $REGION \
      --base-image google-22-full/nodejs20 \
      --no-allow-unauthenticated \
      --project=$PROJECT_ID \
--service-account="${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
--set-env-vars=BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS,MENU_SERVICE_URL=$MENU_SERVICE_URL \
  --max-instances=1 \
  --quiet

輸出內容範例:

Done.                                                                                                                                                                                    
Service [process-thumbnails] revision [process-thumbnails-00001-abc] has been deployed and is serving 100 percent of traffic.
Service URL: https://process-thumbnails-000000000.us-east1.run.app

建立觸發條件:

gcloud eventarc triggers create process-thumbnails-trigger \
     --location=$REGION \
     --destination-run-service=process-thumbnails \
    --destination-run-region=$REGION \
     --event-filters="type=google.cloud.storage.object.v1.finalized" \
     --event-filters="bucket=$UPLOAD_BUCKET_NAME" \
     --service-account="${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com"

輸出內容範例:

Creating trigger [process-thumbnails-trigger] in project [qwiklabs-gcp-02-53f8532696e1], location [us-east1]...done.                                                                     
WARNING: It may take up to 2 minutes for the new trigger to become active.

如果觸發事件部署作業因權限問題而失敗,請等待先前步驟中的 IAM 變更生效。這項作業通常需要 1 到 2 分鐘的時間,然後再重新嘗試部署。

錯誤輸出內容範例:

...If you recently started to use Eventarc, it may take a few minutes before all necessary permissions are propagated to the Service Agent...
[...] 

在 Cloud 控制台中查看為函式建立的 Cloud Run 服務:

546c5c951cf0f2f.png

在 Cloud 控制台中,查看為函式建立的 Eventarc 觸發條件:

dec11309016b09ac.png

在 Cloud 控制台中,查看為 Eventarc 觸發事件建立的 Pub/Sub 主題訂閱項目

affe089c39ae1465.png

a4c41ede2af300db.png

9. 測試並驗證端對端解決方案

將新相片上傳至 Cloud Storage,並在圖片分析期間監控管道的進度。您將監控 Cloud 函式記錄,測試端對端解決方案。

上傳圖片

ab7b43f876f9c3a9.jpeg

  1. 將這個圖片儲存到本機
  2. 將檔案重新命名為 1.jpg
  3. 開啟 Cloud Storage 主控台
  4. 按一下「menu-item-uploads-...」menu-item-uploads-...bucket
  5. 點選「上傳檔案」
  6. 1.jpg 上傳至 Storage 值區
  7. 在 Cloud 控制台中前往「Cloud Run」
  8. 按一下「process-thumbails」
  9. 按一下「LOGS」分頁標籤

fca8e4bafbdf135d.png

  1. 前往 menu-item-thumbnails-$PROJECT_ID Cloud Storage 值區
  2. 確認縮圖圖片已在縮圖值區中建立

1b6dee72a1fde681.png

上傳非食物圖片

為確認函式運作正常,請上傳不含會被歸類為「食物」項目的物件圖片。

c76dd525765f66a6.jpeg

  1. 將這個圖片儲存到本機
  2. 將檔案重新命名為 2.jpg
  3. 開啟 Cloud Storage 主控台
  4. 按一下「menu-item-uploads-...」menu-item-uploads-...bucket
  5. 點選「上傳檔案」
  6. 2.jpg 上傳至儲存體值區
  7. 在 Cloud 控制台中前往「Cloud Run」
  8. 按一下「process-thumbails」
  9. 按一下「LOGS」分頁標籤

18b1e30ee78d3955.png

10. 恭喜!

恭喜,您已完成實驗室!

下一步:

探索其他 Cymbal Eats 程式碼研究室:

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取本教學課程所用資源的費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。

刪除專案

如要避免付費,最簡單的方法就是刪除您為了本教學課程所建立的專案。