1. 總覽
在本程式碼研究室中,您將建立新的 Cloud Run 服務 (映像檔垃圾收集器),並透過 Eventarc (Cloud Run 中用於接收事件的新服務) 觸發該服務。從圖片 bucket 刪除圖片時,服務會收到來自 Eventarc 的事件。然後從縮圖 bucket 刪除圖片,並從 Firestore 圖片集合中移除。

課程內容
- Cloud Run
- Cloud Storage
- Cloud Firestore
- Eventarc
2. 設定和需求
自修實驗室環境設定
- 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶。



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

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

這部虛擬機器搭載各種您需要的開發工具,並提供永久的 5GB 主目錄,而且可在 Google Cloud 運作,大幅提升網路效能並強化驗證功能。本實驗室的所有工作都可在瀏覽器上完成。
3. Eventarc 簡介
Eventarc 可輕鬆將 Cloud Run 服務連結至各種來源的事件。並為您處理事件擷取、傳送、安全防護、授權和錯誤處理工作。

您可以從 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 Events 程式庫,讀取 Eventarc 傳送的 CloudEvents。Express 是 JavaScript / Node 網頁架構,Bluebird 用於處理 Promise。
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 是我們使用的 Node 網路架構;Bluebird 是處理 JavaScript Promise 的程式庫;Storage 和 Firestore 則分別用於處理 Google Cloud Storage (我們的圖片值區) 和 Cloud Firestore 資料儲存區。此外,我們需要 CloudEvent 從 Google Events 程式庫讀取 Eventarc StoreObjectData 傳送的 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;
知道圖片名稱後,我們就能從縮圖 bucket 刪除圖片:
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
您也可以使用 Google Cloud Buildpacks,讓 Cloud Run 為您建構容器映像檔,不必手動使用 Cloud Build 建構及發布容器映像檔。
執行下列指令,使用 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 使用 Google Cloud Buildpacks 建構容器映像檔,而不使用 Dockerfile.。--no-allow-unauthenticated 標記會將 Cloud Run 服務設為內部服務,只會由特定服務帳戶觸發。稍後,您將使用具備 run.invoker 角色的預設 Compute 服務帳戶建立觸發程序,以便呼叫內部 Cloud Run 服務。
9. 建立觸發條件
在 Eventarc 中,觸發條件會定義哪些服務應接收哪些類型的事件。在本例中,您希望服務在 bucket 中的檔案遭到刪除時收到事件。
將觸發條件的位置設為與上傳圖片 bucket 相同的區域:
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 bucket 並刪除其中一張圖片。您應該會在服務的記錄中看到,服務已刪除 thumbnails 值區中的相關圖片,並從 pictures Firestore 集合中刪除該圖片的文件。

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 中接收事件的新服務。從圖片 bucket 刪除圖片時,服務會收到來自 Eventarc 的事件。然後從縮圖 bucket 刪除圖片,並從 Firestore 圖片集合中移除。
涵蓋內容
- Cloud Run
- Cloud Storage
- Cloud Firestore
- Eventarc