使用 Eventarc 和 Cloud Functions (第 2 代) 从 Cloud Storage 触发事件处理

1. 概览

在本实验中,您将学习如何使用 Cloud Storage 存储分区事件和 Eventarc 来触发事件处理。您将使用 Cloud Functions (第 2 代) 来分析数据和处理图片。该函数将使用 Google 的 Vision API,并将生成的图片保存回 Cloud Storage 存储分区。

4756e4c218d84e26

学习内容

如何构建图像处理流水线。

  • 配置存储分区
  • 创建 Cloud Functions 函数以读取和写入 Cloud Storage 中的对象
  • 集成 Vision API 以检测食物图片
  • 部署 Cloud Functions 函数
  • 部署 Eventarc 触发器
  • 测试并验证端到端解决方案

前提条件

  • 本实验假定您熟悉 Cloud 控制台和 Shell 环境。
  • 以前有 Cloud Storage、Cloud Functions 或 Vision API 经验,但不是硬性要求。

2. 设置和要求

Cloud 项目设置

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

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串。您可以随时对其进行更新。
  • 项目 ID 在所有 Google Cloud 项目中是唯一的,并且是不可变的(一经设置便无法更改)。Cloud 控制台会自动生成一个唯一字符串;通常您不在乎这是什么在大多数 Codelab 中,您都需要引用项目 ID(它通常标识为 PROJECT_ID)。如果您不喜欢生成的 ID,可以再随机生成一个 ID。或者,您也可以尝试自己的项目 ID,看看是否可用。完成此步骤后便无法更改该 ID,并且该 ID 在项目期间会一直保留。
  • 此外,还有第三个值,即某些 API 使用的项目编号,供您参考。如需详细了解所有这三个值,请参阅文档
  1. 接下来,您需要在 Cloud 控制台中启用结算功能,以便使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。如需关停资源,以免产生超出本教程范围的结算费用,您可以删除自己创建的资源或删除整个项目。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。

激活 Cloud Shell

点击搜索栏右侧的图标,激活 Cloud Shell。

8613854df02635a3

环境设置

  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=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. 启用实验所需的 API。(Qwiklabs 特定步骤)
gcloud services disable cloudfunctions.googleapis.com
gcloud services enable cloudfunctions.googleapis.com
  1. 克隆存储库
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git && cd cymbal-eats/cloud-functions

3. 配置 Cloud Storage 存储分区

创建存储分区

为您的图片处理流水线创建上传 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 Functions 函数创建自定义服务账号以处理缩略图:

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

触发函数

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 框架注册 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 客户端库支持多种热门编程语言。要开始使用这些库,您必须安装客户端库

创建图片注释器客户端

要使用官方客户端 SDK 访问 Google API,您需要根据 API 的发现文档(向 SDK 描述 API)创建一个服务对象。您需要使用自己的凭据从 Vision API 的发现服务中提取它。

index.js

const client = new vision.ImageAnnotatorClient();

构建 Vision API 请求

Vision API 可以在请求正文中以 base64 编码的字符串形式发送图片文件的内容,从而对图片文件执行特征检测。

使用 images 资源构建请求来为图片添加注释。对此 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 Functions 函数

此图片调整服务是更大的 Cymbal Eats 系统的一部分。在本部分中,您将仅部署与图片处理功能相关的组件。完整安装包含上传图像的界面和存储生成的元数据的下游请求。本实验不会安装这些功能。

在函数部署期间,系统会创建以下组件:

  • Cloud Functions 函数
  • Cloud Run 服务
  • Eventarc 触发器
  • Pub/Sub 主题和订阅

在 cloudshell 终端中,运行以下命令,在 menu-item-uploads-$PROJECT_ID 上部署具有触发器存储分区的 Cloud Functions 函数:

gcloud functions deploy process-thumbnails \
  --gen2 \
  --runtime=nodejs16 \
  --source=thumbnail \
  --region=$REGION \
  --project=$PROJECT_ID \
  --entry-point=process-thumbnails \
  --trigger-bucket=$UPLOAD_BUCKET \
  --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

如果上传存储分区的权限问题导致部署失败,请等待上一步中的 IAM 更改传播。通常需要 1-2 分钟,然后重新尝试部署。

输出示例

Deploying function (may take a while - up to 2 minutes)...done.
[...] 

在 Cloud 控制台中,查看创建的 Cloud Functions 函数

8148dd29e6757603

在 Cloud 控制台中,查看为函数创建的 Cloud Run 服务:

42e970cdd48cae76

在 Cloud 控制台中,查看为函数创建的 Eventarc 触发器:

9441995a5cc62e38

在 Cloud 控制台中,查看为 Eventarc 触发器创建的 Pub/Sub 主题订阅

affe089c39ae1465.png

a4c41ede2af300db.png

9. 测试并验证端到端解决方案

将新照片上传到 Cloud Storage,并在分析图片时监控流水线的进度。您将通过监控 Cloud Functions 函数日志来测试端到端解决方案。

上传合适的图片

2fdd13b63d6148f4.jpeg

  1. 将此映像保存到本地机器
  2. 将文件重命名为 1.jpg
  3. 打开 Cloud Storage 控制台
  4. 点击 menu-item-uploads-... 存储分区
  5. 点击上传文件
  6. 1.jpg 上传到存储分区
  7. 在 Cloud 控制台中,前往 Cloud Functions
  8. 点击 process-thumbails(进程缩略图)
  9. 点击日志标签页

7ab4e783e474c90d

  1. 进入 menu-item-thumbnails-$PROJECT_ID Cloud Storage 存储分区
  2. 验证是否已在缩略图存储分区中创建缩略图图片

84d8023782eb3e0c.png

上传非食品图片

为验证函数能否正常运行,您需要上传一张不包含可归类为“食物”的对象的图片内容。

3226a24251084b28.jpeg

  1. 将此映像保存到本地机器
  2. 将文件重命名为 2.jpg
  3. 打开 Cloud Storage 控制台
  4. 点击 menu-item-uploads-... 存储分区
  5. 点击上传文件
  6. 2.jpg 上传到存储分区
  7. 在 Cloud 控制台中,前往 Cloud Functions
  8. 点击 process-thumbails(进程缩略图)
  9. 点击日志标签页

421c36c342fceea8

10. 恭喜!

恭喜,您已完成本实验!

后续步骤:

探索其他 Cymbal Eats Codelab:

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

删除项目

若要避免产生费用,最简单的方法是删除您为本教程创建的项目。