每天一度:研究室 5 - 刪除圖片後清除所用資源

1. 總覽

在本程式碼研究室中,您將建立新的 Cloud Run 服務 (映像檔垃圾收集器),並由 Eventarc 觸發,這項新服務可用於接收 Cloud Run 中的事件。從圖片值區中刪除圖片時,服務會從 Eventarc 收到事件。然後從縮圖值區刪除圖片,以及從 Firestore 圖片集合中移除該圖片。

d93345bfc235f81e.png

課程內容

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc

2. 設定和需求

自修環境設定

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

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • 「專案名稱」是這項專案參與者的顯示名稱。這是 Google API 不使用的字元字串,您可以隨時更新。
  • 所有 Google Cloud 專案的專案 ID 均不得重複,且設定後即無法變更。Cloud 控制台會自動產生一個不重複的字串。但通常是在乎它何在在大部分的程式碼研究室中,您必須參照專案 ID (通常稱為 PROJECT_ID),因此如果您不喜歡的話,可以再隨機產生一個,或者,您也可以自行嘗試看看是否可用。是「凍結」建立專案後
  • 還有第三個值,也就是部分 API 使用的專案編號。如要進一步瞭解這三個值,請參閱說明文件
  1. 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Cloud 資源/API。執行這個程式碼研究室並不會產生任何費用,如果有的話。如要關閉資源,以免產生本教學課程結束後產生的費用,請按照任「清除所用資源」操作請參閱本程式碼研究室結尾處的操作說明。Google Cloud 的新使用者符合 $300 美元免費試用計畫的資格。

啟動 Cloud Shell

雖然 Google Cloud 可以從筆記型電腦遠端操作,但在本程式碼研究室中,您將使用 Google Cloud Shell,這是一種在 Cloud 中執行的指令列環境。

在 GCP 控制台的右上方,按一下「Cloud Shell」圖示:

bce75f34b2c53987.png

佈建並連線至環境的作業只需幾分鐘的時間。完成後,您應該會看到類似下方的內容:

f6ef2b5f13479f3a.png

這部虛擬機器都裝載了您需要的所有開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,大幅提高網路效能和驗證能力。這個研究室中的所有工作都可以透過瀏覽器完成。

3. Eventarc 簡介

Eventarc 可讓您輕鬆將 Cloud Run 服務與各種來源的事件連結。可以為您處理事件擷取、提交、安全性、授權和錯誤處理作業。

776ed63706ca9683.png

您可以從 Google Cloud 來源和自訂應用程式繪製事件,並將事件發布至 Cloud Pub/Sub,並傳送至 Google Cloud Run 接收器。

來自 Google Cloud 來源廣泛的事件會以 Cloud 稽核記錄的方式傳遞。這些來源的事件傳送的延遲時間和可用性會綁定 Cloud 稽核記錄。只要 Google Cloud 來源的事件發生,系統就會建立對應的 Cloud 稽核記錄項目。

發布至 Cloud Pub/Sub 的自訂應用程式可以將訊息以任何格式指定為 Pub/Sub 主題。

事件觸發條件是篩選機制,可指定要傳送至哪個接收器的事件。

所有事件都會以 CloudEvents v1.0 格式傳送,以便實現跨服務互通性。

4. 事前準備

啟用 API

您需要 Eventarc 服務才能觸發 Cloud Run 服務。請確定已啟用:

gcloud services enable eventarc.googleapis.com

您應該會看到作業成功完成:

Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.

設定服務帳戶

觸發條件會使用預設的運算服務帳戶。將 eventarc.eventReceiver 角色授予預設的運算服務帳戶:

PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format='value(projectNumber)')

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
    --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
    --role roles/eventarc.eventReceiver

pubsub.publisher 角色授予 Cloud Storage 服務帳戶。以下為 Eventarc Cloud Storage 觸發條件所需的資訊:

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

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

如果您是在 2021 年 4 月 8 日當天或之前啟用 Pub/Sub 服務帳戶,請將 iam.serviceAccountTokenCreator 角色授予 Pub/Sub 服務帳戶:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
  --role roles/iam.serviceAccountTokenCreator

5. 複製程式碼

複製程式碼 (如果您尚未在先前的程式碼研究室中):

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop

接著,您就可以前往包含該服務的目錄:

cd serverless-photosharing-workshop/services/garbage-collector/nodejs

服務的檔案版面配置如下:

services
 |
 ├── garbage-collector
      |
      ├── nodejs
           |
           ├── index.js
           ├── package.json

資料夾中有 3 個檔案:

  • index.js 包含 Node.js 程式碼
  • package.json 定義程式庫依附元件

6. 探索程式碼

依附元件

package.json 檔案會定義所需的程式庫依附元件:

{
  "name": "garbage_collector_service",
  "version": "0.0.1",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "cloudevents": "^4.0.1",
    "express": "^4.17.1",
    "@google/events": "^3.1.0",
    "@google-cloud/firestore": "^4.9.9",
    "@google-cloud/storage": "^5.8.3"
  }
}

我們仰賴 Cloud Storage 程式庫來刪除 Cloud Storage 中的圖片。我們宣告 Cloud Firestore 的依附元件,藉此刪除先前儲存的相片中繼資料。此外,我們也依附 CloudEvents SDK 和 Google 事件程式庫,讀取 Eventarc 傳送的 CloudEvents。Express 是 JavaScript / Node 網路架構。Bluebird 的用途是處理承諾。

index.js

讓我們進一步瞭解 index.js 程式碼:

const express = require('express');
const {Storage} = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');
const { HTTP } = require("cloudevents");
const {toStorageObjectData} = require('@google/events/cloud/storage/v1/StorageObjectData');

我們需要各式各樣的依附元件才能執行程式:Express 是我們要使用的節點網路架構,Bluebird 是用來處理 JavaScript 承諾的程式庫,Bluebird 是處理 JavaScript 承諾的程式庫,而 Storage 和 Firestore 可分別與 Google Cloud Storage (即我們的映像檔值區) 以及 Cloud Firestore 資料儲存庫搭配。此外,我們也要求 CloudEvent 讀取 Eventarc StoreObjectData 從 Google 事件程式庫傳送的 CloudEvent,以便讀取 CloudEvent 的 Cloud Storage 事件主體。

const app = express();
app.use(express.json());

app.post('/', async (req, res) => {
    try {
        const cloudEvent = HTTP.toEvent({ headers: req.headers, body: req.body });
        console.log(cloudEvent);


        /* ... */

    } catch (err) {
        console.log(`Error: ${err}`);
        res.status(500).send(err);
    }
});

上面,我們使用 Node 處理常式的結構:應用程式會回應 HTTP POST 要求。這項工具會從 HTTP 要求讀取 CloudEvent,並採取一些錯誤處理機制,以防出現異常。現在,我們來看看這個結構內的內容。

下一步是擷取和剖析 CloudEvent 主體,並擷取物件名稱:

const storageObjectData = toStorageObjectData(cloudEvent.data);
console.log(storageObjectData);

const objectName = storageObjectData.name;

得知圖片名稱後,我們就會從縮圖值區中刪除圖片:

try {
    await storage.bucket(bucketThumbnails).file(objectName).delete();
    console.log(`Deleted '${objectName}' from bucket '${bucketThumbnails}'.`);
}
catch(err) {
    console.log(`Failed to delete '${objectName}' from bucket '${bucketThumbnails}': ${err}.`);
}

最後,也請刪除 Firestore 集合中的相片中繼資料:

try {
    const pictureStore = new Firestore().collection('pictures');
    const docRef = pictureStore.doc(objectName);
    await docRef.delete();

    console.log(`Deleted '${objectName}' from Firestore collection 'pictures'`);
}
catch(err) {
    console.log(`Failed to delete '${objectName}' from Firestore: ${err}.`);
}

res.status(200).send(`Processed '${objectName}'.`);

現在,讓我們的 Node 指令碼監聽傳入要求。此外,請檢查是否已設定必要的環境變數:

app.listen(PORT, () => {
    if (!bucketThumbnails) throw new Error("BUCKET_THUMBNAILS not set");
    console.log(`Started service on port ${PORT}`);
});

7. 在本機測試

先在本機測試程式碼,確保程式碼能正常運作再部署至雲端。

garbage-collector/nodejs 資料夾中,安裝 npm 依附元件並啟動伺服器:

export BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT

npm install; npm start

如果一切順利,則應透過通訊埠 8080 啟動伺服器:

Started service on port 8080

使用 CTRL-C 退出。

8. 建構並部署至 Cloud Run

部署至 Cloud Run 之前,請將 Cloud Run 區域設為下列其中一個支援的區域和平台:managed

REGION=europe-west1
gcloud config set run/region $REGION
gcloud config set run/platform managed

您可以檢查設定是否完成:

gcloud config list

...
[run]
platform = managed
region = europe-west1

除了透過 Cloud Build 手動建構及發布容器映像檔,您也可以透過 Cloud Run 使用 Google Cloud Buildpacks 來建構容器映像檔。

執行下列指令,使用 Google Cloud Buildpack 建構容器映像檔,然後部署至 Cloud Run:

SERVICE_NAME=garbage-collector-service

gcloud run deploy $SERVICE_NAME \
    --source . \
    --no-allow-unauthenticated \
    --update-env-vars BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS

請注意 –-source 旗標。這個標記會標記 Cloud Run 在沒有 Dockerfile. 的情況下使用 Google Cloud Buildpacks 來建構容器映像檔。--no-allow-unauthenticated 旗標會讓 Cloud Run 服務成為只會由特定服務帳戶觸發的內部服務。稍後您將使用預設運算服務帳戶建立觸發條件,該帳戶具備 run.invoker 角色,可以呼叫內部 Cloud Run 服務。

9. 建立觸發條件

在 Eventarc 中,觸發條件會定義要取得哪種服務的事件。在此範例中,您希望服務在檔案從值區中刪除時接收事件。

在與上傳圖片值區相同的區域中,設定觸發條件的位置:

gcloud config set eventarc/location eu

建立 AuditLog 觸發條件來篩選 storage.objects.delete 事件,並傳送至 Cloud Run 服務:

BUCKET_IMAGES=uploaded-pictures-$GOOGLE_CLOUD_PROJECT

gcloud eventarc triggers create trigger-$SERVICE_NAME \
  --destination-run-service=$SERVICE_NAME \
  --destination-run-region=$REGION \
  --event-filters="type=google.cloud.storage.object.v1.deleted" \
  --event-filters="bucket=$BUCKET_IMAGES" \
  --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

您可以使用下列指令再次檢查觸發條件是否建立完成:

gcloud eventarc triggers list

10. 測試服務

如要測試服務是否正常運作,請前往 uploaded-pictures 值區並刪除其中一張圖片。您應該會在服務記錄中看到它刪除 thumbnails 值區中的相關圖片,並從 pictures Firestore 集合中刪除其文件。

519abf90e7ea4d12.png

11. 清除 (選用)

如果不想繼續參加本系列的其他研究室課程,您可以清理資源來節省成本,並成為良好的雲端公民。您可以按照下列步驟個別清除資源。

刪除服務:

gcloud run services delete $SERVICE_NAME -q

刪除 Eventarc 觸發條件:

gcloud eventarc triggers delete trigger-$SERVICE_NAME -q

或者,您也可以刪除整個專案:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

12. 恭喜!

恭喜!您建立了 Cloud Run 服務「映像檔垃圾收集器」,將由 Eventarc 觸發,這項新服務可用於接收 Cloud Run 中的事件。從圖片值區中刪除圖片時,服務會從 Eventarc 收到事件。然後從縮圖值區刪除圖片,以及從 Firestore 圖片集合中移除該圖片。

涵蓋內容

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc