本教程演示了如何使用 Cloud Run、Cloud Vision API 和 ImageMagick 检测上传到 Cloud Storage 存储桶的令人反感的图片并对其进行模糊处理。本教程基于将 Pub/Sub 与 Cloud Run 搭配使用教程构建而成。
本教程将介绍如何修改现有示例应用。如果需要,您还可以下载已完成的示例。
目标
- 编写、构建异步数据处理服务并将其部署到 Cloud Run。
- 通过将文件上传到 Cloud Storage 来调用该服务,从而创建 Pub/Sub 消息。
- 使用 Cloud Vision API 检测暴力或成人内容。
- 使用 ImageMagick 对令人反感的图片进行模糊处理。
- 上传一张肉食僵尸的图片来测试服务。
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
准备工作
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Artifact Registry, Cloud Build, Pub/Sub, Cloud Run, Cloud Storage and Cloud Vision APIs.
- 安装并初始化 gcloud CLI。
- 更新组件:
gcloud components update
- 按照使用 Pub/Sub 教程中的说明,设置 Pub/Sub 主题、安全推送订阅和初始 Cloud Run 服务来处理消息
所需的角色
如需获得完成本教程所需的权限,请让您的管理员为您授予项目的以下 IAM 角色:
-
Cloud Build Editor (
roles/cloudbuild.builds.editor
) -
Cloud Run Admin (
roles/run.admin
) -
Logs View Accessor (
roles/logging.viewAccessor
) -
Project IAM Admin (
roles/resourcemanager.projectIamAdmin
) -
Pub/Sub Admin (
roles/pubsub.admin
) -
Service Account User (
roles/iam.serviceAccountUser
) -
Service Usage Consumer (
roles/serviceusage.serviceUsageConsumer
) -
Storage Admin (
roles/storage.admin
)
如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
设置 gcloud 默认值
要配置您的 Cloud Run 服务的 gcloud 默认值,请执行以下操作:
设置默认项目:
gcloud config set project PROJECT_ID
将 PROJECT_ID 替换为您在本教程中创建的项目的名称。
为您选择的区域配置 gcloud:
gcloud config set run/region REGION
将 REGION 替换为您选择的受支持的 Cloud Run 区域。
Cloud Run 位置
Cloud Run 是区域级的,这意味着运行 Cloud Run 服务的基础架构位于特定区域,并且由 Google 代管,以便在该区域内的所有可用区以冗余方式提供。
选择用于运行 Cloud Run 服务的区域时,主要考虑该区域能否满足您的延迟时间、可用性或耐用性要求。通常,您可以选择距离用户最近的区域,但除此之外,您还应该考虑 Cloud Run 服务使用的其他 Google Cloud 产品的位置。跨多个位置使用 Google Cloud 产品可能会影响服务的延迟时间和费用。
Cloud Run 可在以下区域使用:
基于层级 1 价格
asia-east1
(台湾)asia-northeast1
(东京)asia-northeast2
(大阪)europe-north1
(芬兰) 二氧化碳排放量低europe-southwest1
(马德里) 二氧化碳排放量低europe-west1
(比利时) 二氧化碳排放量低europe-west4
(荷兰) 二氧化碳排放量低europe-west8
(米兰)europe-west9
(巴黎) 二氧化碳排放量低me-west1
(特拉维夫)us-central1
(爱荷华) 二氧化碳排放量低us-east1
(南卡罗来纳)us-east4
(北弗吉尼亚)us-east5
(哥伦布)us-south1
(达拉斯) 二氧化碳排放量低us-west1
(俄勒冈) 二氧化碳排放量低
基于层级 2 价格
africa-south1
(约翰内斯堡)asia-east2
(香港)asia-northeast3
(韩国首尔)asia-southeast1
(新加坡)asia-southeast2
(雅加达)asia-south1
(印度孟买)asia-south2
(印度德里)australia-southeast1
(悉尼)australia-southeast2
(墨尔本)europe-central2
(波兰,华沙)europe-west10
(柏林) 二氧化碳排放量低europe-west12
(都灵)europe-west2
(英国伦敦) 二氧化碳排放量低europe-west3
(德国法兰克福) 二氧化碳排放量低europe-west6
(瑞士苏黎世) 二氧化碳排放量低me-central1
(多哈)me-central2
(达曼)northamerica-northeast1
(蒙特利尔) 二氧化碳排放量低northamerica-northeast2
(多伦多) 二氧化碳排放量低southamerica-east1
(巴西圣保罗) 二氧化碳排放量低southamerica-west1
(智利圣地亚哥) 二氧化碳排放量低us-west2
(洛杉矶)us-west3
(盐湖城)us-west4
(拉斯维加斯)
如果您已创建 Cloud Run 服务,则可以在 Google Cloud 控制台中的 Cloud Run 信息中心内查看区域。
了解操作顺序
本教程中的数据流遵循以下步骤:
- 用户将图片上传到 Cloud Storage 存储桶。
- Cloud Storage 将关于新文件的消息发布到 Pub/Sub。
- Pub/Sub 将消息推送到 Cloud Run 服务。
- Cloud Run 服务检索 Pub/Sub 消息中引用的图片文件。
- Cloud Run 服务使用 Cloud Vision API 来分析图片。
- 如果检测到暴力或成人内容,Cloud Run 服务会使用 ImageMagick 对图片进行模糊处理。
- Cloud Run 服务将经过模糊处理的图片上传到其他 Cloud Storage 存储桶,以供使用。
后续对经过模糊处理的图片的使用将留给读者自行练习。
创建 Artifact Registry 标准制品库
创建 Artifact Registry 标准制品库以存储您的容器映像:
gcloud artifacts repositories create REPOSITORY \ --repository-format=docker \ --location=REGION
您需要将其中的:
- 将 REPOSITORY 替换为制品库的唯一名称。
- 将 REGION 替换为要用于 Artifact Registry 制品库的 Google Cloud 区域。
设置 Cloud Storage 存储桶
gcloud
创建一个 Cloud Storage 存储桶以上传图片,其中 INPUT_BUCKET_NAME 是全局唯一的存储桶名称:
gcloud storage buckets create gs://INPUT_BUCKET_NAME
Cloud Run 服务仅从此存储桶读取内容。
创建另一个 Cloud Storage 存储桶以接收经过模糊处理的图片,其中 BLURRED_BUCKET_NAME 是全局唯一的存储桶名称:
gcloud storage buckets create gs://BLURRED_BUCKET_NAME
Cloud Run 服务会将经过模糊处理的图片上传到此存储桶。使用单独的存储桶可防止处理后的图片重新触发服务。
默认情况下,Cloud Run 修订版本会以 Compute Engine 默认服务账号身份执行。
但是,如果您使用的是用户管理的服务账号,请确保您已分配必需的 IAM 角色,以便具有可从 INPUT_BUCKET_NAME 读取数据的
storage.objects.get
权限以及可将数据上传到 BLURRED_BUCKET_NAME 的storage.objects.create
权限。
Terraform
如需了解如何应用或移除 Terraform 配置,请参阅基本 Terraform 命令。
创建两个 Cloud Storage 存储桶:一个用于上传原始图片,另一个用于 Cloud Run 服务,以上传经过模糊处理的图片。
若要使用全局唯一名称创建两个 Cloud Storage 存储桶,请将以下内容添加到现有 main.tf
文件中:
默认情况下,Cloud Run 修订版本会以 Compute Engine 默认服务账号身份执行。
但是,如果您使用的是用户管理的服务账号,请确保您已分配必需的 IAM 角色,以便具有可从 google_storage_bucket.imageproc_input
读取数据的 storage.objects.get
权限以及可将数据上传到 google_storage_bucket.imageproc_output
的 storage.objects.create
权限。
在以下步骤中,您将创建并部署一项服务,用于处理上传到 INPUT_BUCKET_NAME 的文件通知。请在部署并测试服务后启用通知递送,以避免过早调用新服务。
修改 Pub/Sub 教程示例代码
本教程基于使用 Pub/Sub 教程中汇编的代码构建而成。如果您尚未完成这一基础教程,请立即查看并完成(可跳过清理步骤),然后返回此处来添加图片处理行为。
添加图片处理代码
为了便于阅读和测试,图片处理代码与请求处理是彼此独立的。要添加图片处理代码,请执行以下操作:
切换到 Pub/Sub 教程示例代码的目录。
添加代码以导入图片处理依赖项,包括与 Google Cloud 服务、ImageMagick 和文件系统集成的库。
Node.js
在编辑器中打开一个新的image.js
文件,然后复制以下内容:Python
在编辑器中打开一个新的image.py
文件,然后复制以下内容:Go
在编辑器中打开一个新的imagemagick/imagemagick.go
文件,然后复制以下内容:Java
在编辑器中打开一个新的src/main/java/com/example/cloudrun/ImageMagick.java
文件,然后复制以下内容:添加代码以接收作为事件对象的 Pub/Sub 消息并控制图片处理。
该事件包含最初上传的图片的相关数据。此代码通过查看 Cloud Vision 对暴力或成人内容的分析结果来确定图片是否需要进行模糊处理。
Node.js
Python
Go
Java
从上面创建的 Cloud Storage 输入存储桶检索引用的图片,使用 ImageMagick 转换具有模糊效果的图片,并将结果上传到输出存储桶。
Node.js
Python
Go
Java
将图片处理集成到 Pub/Sub 示例代码中
要修改现有服务以整合图片处理代码:
为您的服务添加新的依赖项,包括 Cloud Vision 和 Cloud Storage 客户端库:
Node.js
npm install --save gm @google-cloud/storage @google-cloud/vision
Python
添加必要的客户端库,让您的requirements.txt
如下所示:Go
Go 示例应用使用 go 模块,上述imagemagick/imagemagick.go
import 语句中添加的新依赖项会通过下一个需要它们的命令自动下载。Java
在pom.xml
中的<dependencyManagement>
下添加以下依赖项: 在pom.xml
中的<dependencies>
下添加以下依赖项:通过修改
FROM
语句下的Dockerfile
,将 ImageMagick 系统软件包添加到您的容器中。如果使用的是“多阶段”Dockerfile,请将其置于最后一个阶段。Debian/Ubuntu Alpine 请阅读使用系统软件包教程,详细了解如何在 Cloud Run 服务中使用系统软件包。
将现有的 Pub/Sub 消息处理代码替换为全新模糊处理逻辑的函数调用。
Node.js
app.js
文件定义了 Express.js 应用,并准备了接收到的 Pub/Sub 消息以供使用。进行以下更改:- 添加代码以导入新的
image.js
文件 - 从路由中移除现有的“Hello World”代码
- 添加代码以进一步验证 Pub/Sub 消息
添加代码以调用新的图片处理函数
完成后,代码将如下所示:
Python
main.py
文件定义了 Flask 应用,并准备了接收到的 Pub/Sub 消息以供使用。进行以下更改:- 添加代码以导入新的
image.py
文件 - 从路由中移除现有的“Hello World”代码
- 添加代码以进一步验证 Pub/Sub 消息
添加代码以调用新的图片处理函数
完成后,代码将如下所示:
Go
main.go
文件定义了 HTTP 服务,并准备了接收到的 Pub/Sub 消息以供使用。进行以下更改:- 添加代码以导入新的
imagemagick.go
文件 - 从处理程序中移除现有的“Hello World”代码
- 添加代码以进一步验证 Pub/Sub 消息
- 添加代码以调用新的图片处理函数
Java
PubSubController.java
文件定义了处理 HTTP 请求的控制器,并准备了接收到的 Pub/Sub 消息以供使用。进行以下更改:- 添加新的导入
- 从控制器中移除现有的“Hello World”代码
- 添加代码以进一步验证 Pub/Sub 消息
- 添加代码以调用新的图片处理函数
- 添加代码以导入新的
下载完整示例
要检索完整的图片处理代码示例以供使用,请执行以下操作:
将示例应用代码库克隆到本地机器:
Node.js
git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git
或者,您也可以下载该示例的 zip 文件并将其解压缩。
Python
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
或者,您也可以下载该示例的 zip 文件并将其解压缩。
Go
git clone https://github.com/GoogleCloudPlatform/golang-samples.git
或者,您也可以下载该示例的 zip 文件并将其解压缩。
Java
git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
或者,您也可以下载该示例的 zip 文件并将其解压缩。
切换到包含 Cloud Run 示例代码的目录:
Node.js
cd nodejs-docs-samples/run/image-processing/
Python
cd python-docs-samples/run/image-processing/
Go
cd golang-samples/run/image-processing/
Java
cd java-docs-samples/run/image-processing/
交付代码
交付代码包括三个步骤:使用 Cloud Build 构建容器映像、将容器映像上传到 Artifact Registry,以及将容器映像部署到 Cloud Run。
如需交付代码,请执行以下操作:
构建容器并将其发布到 Artifact Registry 上:
Node.js
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID /REPOSITORY/pubsub
其中,
pubsub
是服务的名称。您需要将其中的:
- 将 PROJECT_ID 替换为您的 Google Cloud 项目 ID
- 将 REPOSITORY 替换为 Artifact Registry 制品库的名称。
- 将 REGION 替换为要用于 Artifact Registry 制品库的 Google Cloud 区域。
成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。 该映像存储在 Artifact Registry 中,并可根据需要重复使用。
Python
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID /REPOSITORY/pubsub
其中,
pubsub
是服务的名称。您需要将其中的:
- 将 PROJECT_ID 替换为您的 Google Cloud 项目 ID
- 将 REPOSITORY 替换为 Artifact Registry 制品库的名称。
- 将 REGION 替换为要用于 Artifact Registry 制品库的 Google Cloud 区域。
成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。 该映像存储在 Artifact Registry 中,并可根据需要重复使用。
Go
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID /REPOSITORY/pubsub
其中,
pubsub
是服务的名称。您需要将其中的:
- 将 PROJECT_ID 替换为您的 Google Cloud 项目 ID
- 将 REPOSITORY 替换为 Artifact Registry 制品库的名称。
- 将 REGION 替换为要用于 Artifact Registry 制品库的 Google Cloud 区域。
成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。 该映像存储在 Artifact Registry 中,并可根据需要重复使用。
Java
此示例使用 Jib 利用常见 Java 工具构建 Docker 映像。无需编写 Dockerfile 或安装 Docker,Jib 便可以优化容器构建。详细了解如何使用 Jib 构建 Java 容器。使用 Dockerfile,配置并构建已安装系统软件包的基本映像,以覆盖 Jib 的默认基本映像:
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID /REPOSITORY/imagemagick
您需要将其中的:
- 将 PROJECT_ID 替换为您的 Google Cloud 项目 ID
- 将 REPOSITORY 替换为 Artifact Registry 制品库的名称。
- 将 REGION 替换为要用于 Artifact Registry 制品库的 Google Cloud 区域。
使用 gcloud 凭据帮助程序,授权 Docker 推送到您的 Artifact Registry。
gcloud auth configure-docker
使用 Jib 构建最终容器并在 Artifact Registry 上发布:
mvn compile jib:build \ -Dimage=REGION-docker.pkg.dev/PROJECT_ID /REPOSITORY/pubsub \ -Djib.from.image=REGION-docker.pkg.dev/PROJECT_ID /REPOSITORY/imagemagick
您需要将其中的:
- 将 PROJECT_ID 替换为您的 Google Cloud 项目 ID
- 将 REPOSITORY 替换为 Artifact Registry 制品库的名称。
- 将 REGION 替换为要用于 Artifact Registry 制品库的 Google Cloud 区域。
使用您在使用 Cloud Pub/Sub 教程中所用的同一服务名称,运行以下命令来部署您的服务:
Node.js
gcloud run deploy pubsub-tutorial --image REGION-docker.pkg.dev/PROJECT_ID /REPOSITORY/pubsub --set-env-vars=BLURRED_BUCKET_NAME=BLURRED_BUCKET_NAME --no-allow-unauthenticated
Python
gcloud run deploy pubsub-tutorial --image REGION-docker.pkg.dev/PROJECT_ID /REPOSITORY/pubsub --set-env-vars=BLURRED_BUCKET_NAME=BLURRED_BUCKET_NAME --no-allow-unauthenticated
Go
gcloud run deploy pubsub-tutorial --image REGION-docker.pkg.dev/PROJECT_ID /REPOSITORY/pubsub --set-env-vars=BLURRED_BUCKET_NAME=BLURRED_BUCKET_NAME --no-allow-unauthenticated
Java
gcloud run deploy pubsub-tutorial --image REGION-docker.pkg.dev/PROJECT_ID /REPOSITORY/pubsub --set-env-vars=BLURRED_BUCKET_NAME=BLURRED_BUCKET_NAME --memory 512M --no-allow-unauthenticated
其中,
pubsub
是容器名称,pubsub-tutorial
是服务名称。请注意,容器映像会部署到您之前在设置 gcloud 默认值下配置的服务和区域 (Cloud Run)。您需要将其中的:- 将 PROJECT_ID 替换为您的 Google Cloud 项目 ID
- 将 REPOSITORY 替换为 Artifact Registry 制品库的名称。
- 将 REGION 替换为要用于 Artifact Registry 制品库的 Google Cloud 区域。
- 将 BLURRED_BUCKET_NAME 替换为您之前创建来接收经过模糊处理的图片的 Cloud Storage 存储桶,以设置环境变量。
--no-allow-unauthenticated
标志限制对服务未经身份验证的访问。通过将该服务保留为不公开状态,您可以依赖 Cloud Run 的自动 Pub/Sub 集成功能对请求进行身份验证。如需详细了解如何进行此项配置,请参阅与 Pub/Sub 集成。如需详细了解基于 IAM 的身份验证,请参阅管理访问权限。等待部署完成,这可能需要半分钟左右的时间。 成功完成时,命令行会显示服务网址。
开启 Cloud Storage 通知
配置 Cloud Storage,以便在上传或更改文件(称为对象)时将消息发布到 Pub/Sub 主题。将通知发送到之前创建的主题,以便上传任何新文件都会调用该服务。
gcloud
gcloud storage service-agent --project=PROJECT_ID gcloud storage buckets notifications create gs://INPUT_BUCKET_NAME --topic=myRunTopic --payload-format=json
myRunTopic
是您在上一个教程中创建的主题。
将 INPUT_BUCKET_NAME 替换为您在创建存储桶时使用的名称。
如需详细了解存储桶通知,请阅读对象更改通知。
Terraform
如需了解如何应用或移除 Terraform 配置,请参阅基本 Terraform 命令。
为了启用通知,项目唯一的 Cloud Storage 服务账号必须存在,并且拥有对 Pub/Sub 主题的 IAM 权限 pubsub.publisher
。若要授予此权限并创建 Cloud Storage 通知,请将以下内容添加到现有 main.tf
文件:
试试看
上传一张令人反感的图片,比如这张肉食僵尸图片:
curl -o zombie.jpg https://cdn.pixabay.com/photo/2015/09/21/14/24/zombie-949916_960_720.jpg gcloud storage cp zombie.jpg gs://INPUT_BUCKET_NAME
其中,INPUT_BUCKET_NAME 是您之前为了上传图片而创建的 Cloud Storage 存储桶。
进入服务日志:
- 前往 Google Cloud 控制台中的 Cloud Run 页面
- 点击
pubsub-tutorial
服务。 - 选择日志标签页。您可能需要等待一些时间才能看到日志。 如果您没有立即看到日志,请稍等片刻再检查一次。
查找
Blurred image: zombie.png
消息。您可以在之前创建的 BLURRED_BUCKET_NAME Cloud Storage 存储桶中查看经过模糊处理的图片:在 Google Cloud 控制台中的 Cloud Storage 页面找到该存储桶
清理
如果您为本教程创建了一个新项目,请删除项目。 如果您使用的是现有项目,希望保留此项目且不保留本教程中添加的任何更改,请删除为教程创建的资源。
删除项目
为了避免产生费用,最简单的方法是删除您为本教程创建的项目。
如需删除项目,请执行以下操作:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
删除教程资源
删除您在本教程中部署的 Cloud Run 服务:
gcloud run services delete SERVICE-NAME
其中,SERVICE-NAME 是您选择的服务名称。
您还可以从 Google Cloud 控制台中删除 Cloud Run 服务。
移除您在教程设置过程中添加的 gcloud 默认区域配置:
gcloud config unset run/region
移除项目配置:
gcloud config unset project
删除在本教程中创建的其他 Google Cloud 资源:
- 删除 Pub/Sub 主题
myRunTopic
- 删除 Pub/Sub 订阅
myRunSubscription
- 从 Artifact Registry 中删除容器映像。
- 删除调用方服务账号
cloud-run-pubsub-invoker@PROJECT_ID.iam.gserviceaccount.com
- 删除 Cloud Storage 存储桶(为占位符
INPUT_BUCKET_NAME
和BLURRED_BUCKET_NAME
而创建)
- 删除 Pub/Sub 主题
后续步骤
- 详细了解如何使用 Cloud Storage 通过 Cloud Run 保留数据。
- 了解如何使用 Cloud Vision API 检测露骨内容之外的信息。
- 探索有关 Google Cloud 的参考架构、图表和最佳做法。查看我们的 Cloud 架构中心。