1. 简介
Eventarc 让您可以轻松地将 Cloud Run 服务与各种来源的事件连接起来。您可以用它来构建事件驱动型架构,其中微服务是松散耦合和分布式的。它会为您处理事件提取、传递、安全、授权和错误处理。
Workflows 是一个全托管式编排平台,可按照您定义的顺序(工作流)执行服务。这些工作流可以结合使用托管在 Cloud Run 或 Cloud Functions 上的服务、Google Cloud 服务(例如 Cloud Vision AI 和 BigQuery)以及任何基于 HTTP 的 API。
在此 Codelab 中,您将构建一个用于处理映像的事件驱动型微服务编排。您将使用 Workflows 来编排处理 4 张图片的 Cloud Functions 函数的顺序、输入和输出。然后,您将使编排与 Eventarc 以松散耦合的方式响应 Cloud Storage 事件。
最终,您将获得一个灵活而结构化的无服务器架构来处理图片。
学习内容
- Eventarc 和 Workflows 概览
- 如何部署 Cloud Functions 服务
- 如何使用 Workflows 编排服务
- 如何使用 Eventarc 让 Workflows 响应 Cloud Storage 事件
2. 设置和要求
自定进度的环境设置
- 登录 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
虽然可以通过笔记本电脑对 Google Cloud 进行远程操作,但在此 Codelab 中,您将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。
在 Google Cloud 控制台 中,点击右上角工具栏中的 Cloud Shell 图标:
预配和连接到环境应该只需要片刻时间。完成后,您应该会看到如下内容:
这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5 GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证功能。您在此 Codelab 中的所有工作都可以在浏览器中完成。您无需安装任何程序。
设置 gcloud
在 Cloud Shell 中,设置项目 ID 以及要将应用部署到的区域。将它们保存为 PROJECT_ID
和 REGION
变量。如需了解可用区域,请参阅 Cloud Functions 位置。
PROJECT_ID=your-project-id gcloud config set project $PROJECT_ID
获取源代码
该应用的源代码位于 eventarc-samples 代码库的 processing-pipelines
文件夹中。
克隆代码库:
git clone https://github.com/GoogleCloudPlatform/eventarc-samples.git
转到 eventarc-samples/processing-pipelines
文件夹:
cd eventarc-samples/processing-pipelines
3. 架构概览
该应用的架构如下所示:
- 图片保存到输入存储分区,此存储分区会生成 Cloud Storage 创建事件。
- Eventarc 通过 Cloud Storage 触发器读取 Cloud Storage 创建事件,并作为 CloudEvent 传递给 Workflows。
- 在工作流的第一步中,Cloud Functions 函数 Filter 使用 Vision API 来确定图片是否安全。如果图片是安全的,Workflows 会继续执行后续步骤。
- 在工作流的第二步,Labeler(一项 Cloud Functions 函数服务)使用 Vision API 提取图片标签,并将标签保存到输出存储分区。
- 第三步,Resizer(另一个 Cloud Functions 函数服务)使用 ImageSharp 调整图片大小,并将调整后的图片保存到输出存储分区。
- 在最后一步中,另一个 Cloud Functions 函数服务 Watermarker 使用 ImageSharp 将标签添加者的标签水印添加到调整后的图片上,并将图片保存到输出存储分区。
应用由 Cloud Storage 事件触发,因此属于事件驱动型应用。图片的处理是在工作流中进行的,因此也是一种编排。最终,它是一种事件驱动型编排,适用于灵活而结构化的无服务器架构来处理图片。
4. 创建存储分区
创建一个输入存储分区以供用户上传图片,并为图片处理流水线创建一个输出存储分区,以保存已处理的图片。
在 Cloud Shell 中运行下面的命令:
REGION=us-central1 BUCKET1=$PROJECT_ID-images-input BUCKET2=$PROJECT_ID-images-output gsutil mb -l $REGION gs://$BUCKET1 gsutil mb -l $REGION gs://$BUCKET2
5. 部署过滤器服务
我们先部署第一项服务。此 Cloud Functions 服务可接收存储分区和文件信息,确定使用 Vision API 处理图片是否安全并返回结果。
首先,为 Cloud Functions gen2 和 Vision API 启用所需的服务:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ run.googleapis.com \ vision.googleapis.com
在顶级 processing-pipelines
文件夹中,部署该服务:
SERVICE_NAME=filter gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --entry-point Filter.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v3/filter/csharp
部署函数后,在变量中设置服务网址,稍后需要用到该网址:
FILTER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
6. 部署标签添加者服务
第二个 Cloud Functions 服务接收存储分区和文件信息,使用 Vision API 提取图片标签,并将标签保存到输出存储分区。
在顶级 processing-pipelines
文件夹中,部署该服务:
SERVICE_NAME=labeler gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Labeler.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/labeler/csharp
部署函数后,在变量中设置服务网址,稍后需要用到该网址:
LABELER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
7. 部署调整大小器服务
此 Cloud Functions 服务会接收存储分区和文件信息,使用 ImageSharp 调整图片大小,并将图片保存到输出存储分区。
在顶级 processing-pipelines
文件夹中,部署该服务:
SERVICE_NAME=resizer gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Resizer.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/resizer/csharp \ --timeout=120s
请注意 timeout
值为 2 分钟,以便让调整器函数有额外的处理时间。
部署函数后,在变量中设置服务网址,稍后需要用到该网址:
RESIZER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
8. 部署水印服务
此 Cloud Functions 服务会接收存储分区、文件和标签信息,读取文件,使用 ImageSharp 将标签添加为图片水印,然后将图片保存到输出存储分区。
在顶级 processing-pipelines
文件夹中,部署该服务:
SERVICE_NAME=watermarker gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Watermarker.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/watermarker/csharp
部署函数后,在变量中设置服务网址,稍后需要用到该网址:
WATERMARKER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
此时,应该部署并运行所有四个 Cloud Functions 函数:
9. 定义和部署工作流
使用 Workflows 将过滤器、标签添加者、调整大小器和水位标记服务整合到一个工作流中。Workflows 对这些服务进行编排,按照我们定义的参数调用顺序。
首先,为 Workflows 启用所需的服务:
gcloud services enable \ workflows.googleapis.com \ workflowexecutions.googleapis.com
定义
工作流会接收 CloudEvent 作为参数。创建触发器后,此代码将来自 Eventarc。在前两个步骤中,Workflows 会记录事件,并从事件中提取存储分区和文件信息:
main: params: [event] steps: - log_event: call: sys.log args: text: ${event} severity: INFO - extract_bucket_and_file: assign: - bucket: ${event.data.bucket} - file: ${event.data.name}
在 filter
步骤中,Workflows 调用我们之前部署的过滤器服务。然后,它会记录并检查文件安全性:
- filter: call: http.post args: url: FILTER_URL # TODO: Replace auth: type: OIDC body: bucket: ${bucket} file: ${file} result: filterResponse - log_safety: call: sys.log args: text: ${filterResponse.body.safe} severity: INFO - check_safety: switch: - condition: ${filterResponse.body.safe == true} next: label next: end
在 label
步骤中,Workflows 调用标签添加者服务并捕获响应(前 3 个标签):
- label: call: http.post args: url: LABELER_URL # TODO: Replace auth: type: OIDC body: bucket: ${bucket} file: ${file} result: labelResponse
在 resize
步骤中,Workflows 调用调整器服务并捕获响应(调整后图片的存储分区和文件):
- resize: call: http.post args: url: RESIZER_URL # TODO: Replace auth: type: OIDC body: bucket: ${bucket} file: ${file} result: resizeResponse
在 watermark
步骤中,Workflows 使用调整后的图片和标签调用水印服务,并捕获结果(调整大小后带水印的图片):
- watermark: call: http.post args: url: WATERMARKER_URL # TODO: Replace auth: type: OIDC body: bucket: ${resizeResponse.body.bucket} file: ${resizeResponse.body.file} labels: ${labelResponse.body.labels} result: watermarkResponse
在 final
步骤中,Workflows 从标签添加者、调整器和水印服务返回 HTTP 状态代码:
- final: return: label: ${labelResponse.code} resize: ${resizeResponse.code} watermark: ${watermarkResponse.code}
部署
在部署工作流之前,请确保通过手动方式或使用 sed
将服务网址替换为已部署函数的网址:
在顶级 processing-pipelines
文件夹中,前往 workflows.yaml
文件所在的 image-v3
文件夹:
cd image-v3/
运行 sed
,将占位符网址替换为已部署服务的实际网址:
sed -i -e "s|FILTER_URL|${FILTER_URL}|" workflow.yaml sed -i -e "s|LABELER_URL|${LABELER_URL}|" workflow.yaml sed -i -e "s|RESIZER_URL|${RESIZER_URL}|" workflow.yaml sed -i -e "s|WATERMARKER_URL|${WATERMARKER_URL}|" workflow.yaml
部署工作流:
WORKFLOW_NAME=image-processing gcloud workflows deploy $WORKFLOW_NAME \ --source=workflow.yaml \ --location=$REGION
几秒钟后,您应该会在控制台中看到部署的工作流:
10. 创建触发器
现在,工作流已部署,最后一步是使用 Eventarc 触发器将其连接到 Cloud Storage 事件。
一次性设置
首先,为 Eventarc 启用所需的服务:
gcloud services enable \ eventarc.googleapis.com
创建将在 Eventarc 触发器中使用的服务账号。
SERVICE_ACCOUNT=eventarc-trigger-imageproc-sa gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Eventarc trigger image processing service account"
授予 workflows.invoker
角色,以便服务账号可用于从 Eventarc 调用 Workflows:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/workflows.invoker \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
授予 eventarc.eventReceiver
角色,以便服务账号可以用于
Cloud Storage 触发器:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/eventarc.eventReceiver \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
将 pubsub.publisher
角色授予 Cloud Storage 服务账号。这是 Eventarc 的 Cloud Storage 触发器所必需的:
STORAGE_SERVICE_ACCOUNT="$(gsutil kms serviceaccount -p $PROJECT_ID)" gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$STORAGE_SERVICE_ACCOUNT \ --role roles/pubsub.publisher
创建
运行以下命令以创建触发器。此触发器过滤输入 Cloud Storage 存储分区中的新文件创建事件,并将其传递到我们之前定义的工作流:
TRIGGER_NAME=trigger-image-processing gcloud eventarc triggers create $TRIGGER_NAME \ --location=$REGION \ --destination-workflow=$WORKFLOW_NAME \ --destination-workflow-location=$REGION \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=$BUCKET1" \ --service-account=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
您可以在 Cloud 控制台的 Eventarc 部分看到触发器已创建并准备就绪:
11. 测试流水线
图片处理流水线已准备好接收来自 Cloud Storage 的事件。如需测试流水线,请将图片上传到输入存储分区:
gsutil cp beach.jpg gs://$BUCKET1
上传图片后,您应该会看到 Workflows 执行处于活跃状态:
大约一分钟后,您应该会看到执行成功。您还可以查看工作流的输入和输出:
如果您列出输出存储分区的内容,您应该会看到调整大小后的图片、调整大小和加水印的图片以及该图片的标签:
gsutil ls gs://$BUCKET2 gs://$PROJECT_ID-images-output/beach-400x400-watermark.jpeg gs://$PROJECT_ID-images-output/beach-400x400.png gs://$PROJECT_ID-images-output/beach-labels.txt
如需仔细检查,您可以打开调整大小并添加了水印的图片以查看结果:
12. 恭喜
恭喜,您已完成此 Codelab!
所学内容
- Eventarc 和 Workflows 概览
- 如何部署 Cloud Functions 服务
- 如何使用 Workflows 编排服务
- 如何使用 Eventarc 让 Workflows 响应 Cloud Storage 事件