每日图片:实验 5 - 删除映像后进行清理

每日图片:实验 5 - 删除映像后进行清理

关于此 Codelab

subject上次更新时间:10月 7, 2021
account_circleMete Atamel 编写

1. 概览

在此 Codelab 中,您将创建一个新的 Cloud Run 服务,即映像垃圾回收器,它将由 Eventarc(一项用于在 Cloud Run 中接收事件的新服务)触发。从图片存储分区中删除图片时,服务会收到来自 Eventarc 的事件。然后,它会从缩略图存储分区中删除该图片,并将其从 Firestore 图片集合中移除。

d93345bfc235f81e.png

学习内容

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc

2. 设置和要求

自定进度的环境设置

  1. 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个

96a9c957bc475304

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串,您可以随时对其进行更新。
  • 项目 ID 在所有 Google Cloud 项目中必须是唯一的,并且不可变(一经设置便无法更改)。Cloud Console 会自动生成一个唯一字符串;通常情况下,您无需关注该字符串。在大多数 Codelab 中,您都需要引用项目 ID(它通常标识为 PROJECT_ID),因此如果您不喜欢某个 ID,请再生成一个随机 ID,还可以尝试自己创建一个,并确认是否可用。然后,项目创建后,ID 会处于“冻结”状态。
  • 第三个值是一些 API 使用的项目编号。如需详细了解所有这三个值,请参阅文档
  1. 接下来,您需要在 Cloud Console 中启用结算功能,才能使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。要关闭资源以避免产生超出本教程范围的费用,请按照此 Codelab 末尾提供的任何“清理”说明操作。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。

启动 Cloud Shell

虽然可以通过笔记本电脑对 Google Cloud 进行远程操作,但在此 Codelab 中,您将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。

在 GCP 控制台中,点击右上角工具栏上的 Cloud Shell 图标:

bce75f34b2c53987.png

预配和连接到环境应该只需要片刻时间。完成后,您应该会看到如下内容:

f6ef2b5f13479f3a.png

这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证功能。只需一个浏览器,即可完成本实验中的所有工作。

3. Eventarc 简介

Eventarc 让您可以轻松地将 Cloud Run 服务与各种来源的事件连接起来。它会为您处理事件提取、传递、安全、授权和错误处理。

776ed63706ca9683

您可以从 Google Cloud 来源和发布到 Cloud Pub/Sub 的自定义应用提取事件,并将其传递给 Google Cloud Run 接收器。

来自各种 Google Cloud 来源的事件通过 Cloud Audit Logs 传送。从这些来源传送事件时的延迟时间和可用性都与 Cloud Audit Logs 相关。每当来自 Google Cloud 来源的事件被触发时,系统都会创建相应的 Cloud Audit Log 条目。

发布到 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. 克隆代码

如果之前的 Codelab 中尚未克隆该代码,请执行以下操作:

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 / 节点 Web 框架。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 是我们将使用的节点 Web 框架,Bluebird 是一个用于处理 JavaScript promise 的库,Storage 和 Firestore 分别用于 Google Cloud Storage(我们的映像存储分区)和 Cloud Firestore 数据存储区。此外,我们要求 CloudEvent 从 Google 事件库读取 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);
   
}
});

上面,我们有了节点处理程序的结构:我们的应用会响应 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 Run 使用 Google Cloud Buildpack 为您构建容器映像,而无需使用 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 以在没有 Dockerfile. 的情况下使用 Google Cloud Buildpack 构建容器映像。--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

11. 清理(可选)

如果您不打算继续完成本系列中的其他实验,可以清理资源以节省成本,并成为一个整体优秀的云公民。您可以按以下步骤逐个清理资源。

删除服务:

gcloud run services delete $SERVICE_NAME -q

删除 Eventarc 触发器:

gcloud eventarc triggers delete trigger-$SERVICE_NAME -q

或者,您也可以删除整个项目:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

12. 恭喜!

恭喜!您创建了一项由 Eventarc(用于在 Cloud Run 中接收事件的新服务)触发的 Cloud Run 服务(映像垃圾回收器)。从图片存储分区中删除图片时,服务会收到来自 Eventarc 的事件。然后,它会从缩略图存储分区中删除该图片,并将其从 Firestore 图片集合中移除。

所学内容

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc