1. 概览
在本实验中,您将学习如何使用 Cloud Storage 存储分区事件和 Eventarc 来触发事件处理。您将使用 Cloud Functions (第 2 代) 来分析数据和处理图片。该函数将使用 Google 的 Vision API,并将生成的图片保存回 Cloud Storage 存储分区。
学习内容
如何构建图像处理流水线。
- 配置存储分区
- 创建 Cloud Functions 函数以读取和写入 Cloud Storage 中的对象
- 集成 Vision API 以检测食物图片
- 部署 Cloud Functions 函数
- 部署 Eventarc 触发器
- 测试并验证端到端解决方案
前提条件
- 本实验假定您熟悉 Cloud 控制台和 Shell 环境。
- 以前有 Cloud Storage、Cloud Functions 或 Vision API 经验,但不是硬性要求。
2. 设置和要求
Cloud 项目设置
- 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个。
- 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串。您可以随时对其进行更新。
- 项目 ID 在所有 Google Cloud 项目中是唯一的,并且是不可变的(一经设置便无法更改)。Cloud 控制台会自动生成一个唯一字符串;通常您不在乎这是什么在大多数 Codelab 中,您都需要引用项目 ID(它通常标识为
PROJECT_ID
)。如果您不喜欢生成的 ID,可以再随机生成一个 ID。或者,您也可以尝试自己的项目 ID,看看是否可用。完成此步骤后便无法更改该 ID,并且该 ID 在项目期间会一直保留。 - 此外,还有第三个值,即某些 API 使用的项目编号,供您参考。如需详细了解所有这三个值,请参阅文档。
- 接下来,您需要在 Cloud 控制台中启用结算功能,以便使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。如需关停资源,以免产生超出本教程范围的结算费用,您可以删除自己创建的资源或删除整个项目。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。
激活 Cloud Shell
点击搜索栏右侧的图标,激活 Cloud Shell。
环境设置
- 在 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)")
- 启用实验所需的 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
- 启用实验所需的 API。(Qwiklabs 特定步骤)
gcloud services disable cloudfunctions.googleapis.com
gcloud services enable cloudfunctions.googleapis.com
- 克隆存储库
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git && cd cymbal-eats/cloud-functions
3. 配置 Cloud Storage 存储分区
创建存储分区
为您的图片处理流水线创建上传 Cloud Storage 存储分区和缩略图 Cloud Storage 存储分区。
使用 gsutil mb 命令创建一个唯一名称以创建两个存储分区:
- 先上传图片的上传存储分区
- 缩略图存储分区,用于存储生成的缩略图
创建存储分区以上传新图片:
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”系统将向菜单服务发送一个事件,以更新菜单项的图片和缩略图。
触发函数
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 函数:
在 Cloud 控制台中,查看为函数创建的 Cloud Run 服务:
在 Cloud 控制台中,查看为函数创建的 Eventarc 触发器:
9. 测试并验证端到端解决方案
将新照片上传到 Cloud Storage,并在分析图片时监控流水线的进度。您将通过监控 Cloud Functions 函数日志来测试端到端解决方案。
上传合适的图片
- 将此映像保存到本地机器
- 将文件重命名为 1.jpg
- 打开 Cloud Storage 控制台
- 点击 menu-item-uploads-... 存储分区
- 点击上传文件
- 将 1.jpg 上传到存储分区
- 在 Cloud 控制台中,前往 Cloud Functions。
- 点击 process-thumbails(进程缩略图)
- 点击日志标签页
- 进入 menu-item-thumbnails-$PROJECT_ID Cloud Storage 存储分区
- 验证是否已在缩略图存储分区中创建缩略图图片
上传非食品图片
为验证函数能否正常运行,您需要上传一张不包含可归类为“食物”的对象的图片内容。
- 将此映像保存到本地机器
- 将文件重命名为 2.jpg
- 打开 Cloud Storage 控制台
- 点击 menu-item-uploads-... 存储分区
- 点击上传文件
- 将 2.jpg 上传到存储分区
- 在 Cloud 控制台中,前往 Cloud Functions。
- 点击 process-thumbails(进程缩略图)
- 点击日志标签页
10. 恭喜!
恭喜,您已完成本实验!
后续步骤:
探索其他 Cymbal Eats Codelab:
- 使用 Eventarc 触发 Cloud Workflows
- 从 Cloud Run 连接到 Private CloudSQL
- 从 Cloud Run 连接到全代管式数据库
- 使用 Identity-Aware Proxy (IAP) 保护无服务器应用
- 使用 Cloud Scheduler 触发 Cloud Run 作业
- 安全地部署到 Cloud Run
- 保护 Cloud Run 入站流量
- 从 GKE Autopilot 连接到专用 AlloyDB
清理
为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
删除项目
若要避免产生费用,最简单的方法是删除您为本教程创建的项目。