使用 Eventarc 触发工作流

1. 概览

在本实验中,您将创建一个 Eventarc 触发器,用于将 Pub/Sub 主题连接到 Workflows 服务。Eventarc 让您可以将服务与服务通信分离开来,让您的解决方案更具可扩展性和事件驱动型。您将创建一个工作流,其中包含执行业务流程的多个步骤,以计算在 Cymbal Eats 下单的客户奖励积分。工作流将调用专用 Cloud Run 服务 API 来执行业务逻辑。Cloud Run 服务配置为仅允许内部流量,并且需要进行身份验证。工作流将向 Pub/Sub 主题发布一条消息,通知订单服务计算的奖励积分。

c6d4337a47b55333.png

什么是 Eventarc?

借助 Eventarc,您可以构建事件驱动型架构,而无需实现、自定义或维护底层基础架构。Eventarc 提供了一个标准化解决方案,用于管理分离微服务之间的状态更改流(称为事件)。触发后,Eventarc 会通过 Pub/Sub 订阅将这些事件路由到各个目的地(例如Workflows 或 Cloud Run)来管理交付、安全性、授权、可观测性和错误处理。

Google 事件提供方

  • 超过 90 家 Google Cloud 提供商。这些提供方直接从来源(例如 Cloud Storage)发送事件,或通过 Cloud Audit Logs 条目发送事件。
  • Pub/Sub 提供方。这些提供程序使用 Pub/Sub 消息将事件发送到 Eventarc。

第三方提供商

第三方提供商是指提供 Eventarc 来源的非 Google 实体。

Eventarc 触发器

  • Cloud Pub/Sub 事件。Eventarc 可由发布到 Pub/Sub 主题的消息触发。
  • Cloud Audit Logs (CAL) 事件。Cloud Audit Logs 可为每个 Cloud 项目、文件夹和组织提供管理员活动和数据访问审核日志。
  • 直接事件:Eventarc 可由各种直接事件触发,例如 Cloud Storage 存储分区的更新或 Firebase Remote Config 模板的更新。

事件目的地

  • Workflows
  • Cloud Run
  • GKE
  • Cloud Functions( 第 2 代)

c7ca054200edf1b3.png

什么是 Workflows?

Workflows 是一项全代管式服务,您可利用这种服务集成微服务、任务和 API。Workflows 是一项无服务器服务,可根据您的需求进行扩缩。

Workflows 用例:

  • 事件驱动型工作流对定义的触发器执行。例如,当提交新订单并想计算客户积分时。或者,当订单取消时,可以发布事件,所有感兴趣的服务都将处理该事件。
  • 批处理作业工作流使用 Cloud Scheduler 定期运行作业。例如,夜间作业会检查处于失败状态的菜单项并将其删除。

Workflows 非常适合用于编排服务的工作流。您可以自动执行最长一年的等待和重试流程。

工作流程的优势

  • 配置胜过代码:通过将逻辑移至配置而非编写代码来减少技术债务。
  • 简化架构。借助有状态工作流,您可以直观呈现和监控复杂的服务集成,而无需其他依赖项。
  • 兼顾可靠性和容错能力。利用默认或自定义的重试逻辑以及错误处理功能控制故障,即使其他系统发生故障,也能通过检查点对 Cloud Spanner 进行的每个步骤跟踪进度。
  • 零维护。根据需要进行扩展:无需修补或维护任何内容。您只需在工作流运行时付费,在等待或处于非活动状态时无需支付任何费用。

在本实验中,您将配置一个事件驱动型工作流。

学习内容

在本实验中,您将学习如何完成以下操作:

  • 配置 Pub/Sub 主题和 Eventarc 以触发工作流
  • 配置工作流以调用 Cloud Run 服务并将消息发布到 Pub/Sub
  • 如何在 Cloud Logging 中使用 gcloud CLI 查询 Workflows 结构化日志

前提条件

  • 本实验假定您熟悉 Cloud 控制台和 Cloud Shell 环境。
  • 之前有 Cloud Run 和 Cloud Pub/Sub 经验会有帮助,但并非必需。

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。

eb0157a992f16fa3.png

克隆代码库并导航到该目录,将下面的命令复制并粘贴到终端中,然后按 Enter 键:

git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git && cd cymbal-eats/customer-service

通过运行 lab-setup.sh 部署所需的依赖项

系统将创建以下资源:

  • AlloyDB 集群和实例
  • Artifact Registry,用于存储 Cloud Run 作业和客户服务的容器映像
  • 适用于 Cloud Run 服务和作业的 VPC 访问通道连接器,用于与 AlloyDB 数据库通信
  • 用于创建 AlloyDB 数据库的 Cloud Run 作业
  • Cloud Run 客户服务 - 基于 Java 的微服务(使用 Quarkus 框架)。
./lab-setup.sh

如果系统提示您授权,请点击“授权”以继续。

6356559df3eccdda

设置过程大约需要 10 分钟。

等待脚本完成,并在运行其他步骤之前看到以下输出。

Deploying container to Cloud Run service [customer-service] in project [cymbal-eats-19227-5681] region [us-east1]
OK Deploying new service... Done.                                                   
  OK Creating Revision...
  OK Routing traffic...
Done.
Service [customer-service] revision [customer-service-00001-mid] has been deployed and is serving 100 percent of traffic.
Service URL: https://customer-service-e4p5zon5rq-ue.a.run.app

您可以探索下一部分,然后返回以从下一步继续。

3. 查看工作流程

Workflows 核心概念

工作流包含使用 Workflows 语法(YAML 或 JSON)描述的一系列步骤。

创建工作流后,系统将执行部署,这使得工作流已准备好执行。

执行是指工作流定义中包含的逻辑的单次运行。尚未执行的工作流不会产生费用。所有工作流执行都是独立的,并且该产品的快速扩缩功能支持大量并发执行。

执行控制措施

  • 步骤 - 如需创建工作流,您可以使用 Workflows 语法定义所需的 steps 和执行顺序。每个工作流必须至少有一个步骤。
  • 条件 - 您可以使用 switch 块作为选择机制,允许表达式的值控制工作流的执行流程。
  • 迭代 - 您可以使用 for 循环对一系列数字或一组数据(例如列表或映射)进行迭代。
  • 子工作流 - 子工作流的运行方式与编程语言中的例程或函数类似,你可以封装工作流将多次重复的一个或一组步骤。

触发执行

  • 手动 - 您可以通过 Google Cloud 控制台或命令行(使用 Google Cloud CLI)管理工作流。
  • 程序化 - 适用于 Workflows API 或 REST API 的 Cloud 客户端库可用于管理工作流。
  • 计划 - 您可以使用 Cloud Scheduler 按照特定的计划运行工作流。

运行时参数

您可以通过向主工作流添加 params 字段(位于主代码块中)来访问在运行时传递的数据。main 代码块接受属于任何有效 JSON 数据类型的单个参数。params 字段为工作流用来存储您传入数据的变量命名。

Cloud Run 服务身份验证的工作流

客户服务是此代码库中包含的一个示例应用,该应用在 Cloud Run 上运行,并配置为仅允许来自内部网络且经过身份验证的请求。您将配置 Workflows,以将由 Google 签名的 OpenID Connect(OIDC) 令牌添加到请求中,以便向 Cloud Run 服务进行身份验证。

查看文档,详细了解服务到服务身份验证

工作流身份验证是使用 auth 部分在 args 块下配置的。

rewardsWorkflow.yaml.tmpl

   - create_customer:
        call: http.post
        args:
          url: CUSTOMER_SERVICE_URL/customer
          auth:
            type: OIDC

工作流逻辑

如果客户不存在,此工作流将先进行 API 调用以创建客户,然后更新奖励积分。工作流程会根据订单总金额选择调节系数,以便计算客户的奖励积分。有关详情,请参阅以下示例。

  - calculate_multiplier:
        switch:
          - condition: ${totalAmount < 10}
            steps:
              - set_multiplier1:
                  assign:
                    - multiplier: 2
          - condition: ${totalAmount >= 10 and totalAmount < 25}
            steps:
              - set_multiplier2:
                  assign:
                    - multiplier: 3
          - condition: ${totalAmount >= 25}
            steps:
              - set_multiplier3:
                  assign:
                    - multiplier: 5
    - calculate_rewards:
        assign:
            - rewardPoints: ${customerRecord.rewardPoints * multiplier}

fcd91b2bc5d60347.png

4. 配置和部署 Workflow

设置环境变量:

export REGION=us-east1

export CUSTOMER_SERVICE_URL=$(gcloud run services describe customer-service \
  --platform managed \
  --region $REGION \
  --format=json | jq \
  --raw-output ".status.url")

echo $CUSTOMER_SERVICE_URL

替换工作流模板中的服务网址:

sed "s@CUSTOMER_SERVICE_URL@$CUSTOMER_SERVICE_URL@g" rewardsWorkflow.yaml.tmpl > rewardsWorkflow.yaml

为 Workflows 服务和项目环境变量设置位置:

gcloud config set workflows/location ${REGION}

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
export PROJECT_NAME=$(gcloud projects describe $PROJECT_ID --format='value(name)')

为工作流创建自定义服务账号,并拥有以下权限:

  • 调用 Cloud Run 服务
  • Call Logging API
  • 将消息发布到 PubSub 主题
export WORKFLOW_SERVICE_ACCOUNT=workflows-cloudrun-sa

gcloud iam service-accounts create ${WORKFLOW_SERVICE_ACCOUNT}

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${WORKFLOW_SERVICE_ACCOUNT}@$PROJECT_ID.iam.gserviceaccount.com" \
  --role "roles/run.invoker"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${WORKFLOW_SERVICE_ACCOUNT}@$PROJECT_ID.iam.gserviceaccount.com" \
  --role "roles/logging.logWriter"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${WORKFLOW_SERVICE_ACCOUNT}@$PROJECT_ID.iam.gserviceaccount.com" \
  --role "roles/pubsub.publisher"

部署工作流。工作流配置为使用上一步中创建的服务账号:

export WORKFLOW_NAME=rewardsWorkflow

gcloud workflows deploy ${WORKFLOW_NAME} \
  --source=rewardsWorkflow.yaml \
  --service-account=${WORKFLOW_SERVICE_ACCOUNT}@$PROJECT_ID.iam.gserviceaccount.com

查看工作流来源和其他详细信息(“触发器”标签页)。目前没有配置任何触发器来执行此工作流。您将在下一步中进行设置。

d3527393fb07a9b3.png

5. 配置 Pub/Sub 主题和 Eventarc 触发器

接下来,您将创建两个 Pub/Sub 主题,并配置一个 Eventarc 触发器。

订单服务将向 order-topic 发布包含新订单相关信息的消息。

工作流会向 order-points-topic 发布消息,其中包含有关订单奖励积分和总金额的信息。订单服务(本实验中未部署的部分)会公开一个端点,供 order-points-topic, 的推送订阅用于更新奖励积分和每笔订单的总金额。

创建新的 Pub/Sub 主题:

export TOPIC_ID=order-topic
export ORDER_POINTS_TOPIC_ID=order-points-topic
gcloud pubsub topics create $TOPIC_ID --project=$PROJECT_ID
gcloud pubsub topics create $ORDER_POINTS_TOPIC_ID --project=$PROJECT_ID

为 Eventarc 服务设置位置:

gcloud config set eventarc/location ${REGION}

创建将供 Eventarc 触发器用于执行工作流的自定义服务账号。

export TRIGGER_SERVICE_ACCOUNT=eventarc-workflow-sa

gcloud iam service-accounts create ${TRIGGER_SERVICE_ACCOUNT}

向服务账号授予访问权限以执行工作流。

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member="serviceAccount:${TRIGGER_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/workflows.invoker"

创建 Eventarc 触发器以监听 Pub/Sub 消息并将其传送到 Workflows。

gcloud eventarc triggers create new-orders-trigger \
  --destination-workflow=${WORKFLOW_NAME} \
  --destination-workflow-location=${REGION} \
  --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
  --service-account="${TRIGGER_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --transport-topic=$TOPIC_ID

示例输出:

Creating trigger [new-orders-trigger] in project [qwiklabs-gcp-01-1a990bfcadb3], location [us-east1]...done.     
Publish to Pub/Sub topic [projects/qwiklabs-gcp-01-1a990bfcadb3/topics/order-topic] to receive events in Workflow [rewardsWorkflow].
WARNING: It may take up to 2 minutes for the new trigger to become active.

查看已创建的 Eventarc 触发器

bda445561ad5f4.png

查看为触发器创建的订阅

3fccdda7d5526597

查看工作流程端的更改。已添加新的触发器。

23d338abc16eaac8.png

6. 测试工作流

c6d4337a47b55333.png

为了模拟订单服务,您需要从 Cloud Shell 向 Pub/Sub 主题发送消息,并在 Cloud 控制台中验证 Cloud Run 客户服务日志。

export TOPIC_ID=order-topic
gcloud pubsub topics publish $TOPIC_ID --message '{"userId":"id1","orderNumber":123456,"name":"Angela Jensen","email":"ajensen9090+eats@gmail.com","address":"1845 Denise St","city":"Mountain View","state":"CA","zip":"94043","orderItems":[{"id":7,"createDateTime":"2022-03-17T21:51:44.968584","itemImageURL":"https://images.unsplash.com/photo-1618449840665-9ed506d73a34?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80","itemName":"Curry Plate","itemPrice":12.5,"itemThumbnailURL":"https://images.unsplash.com/photo-1618449840665-9ed506d73a34?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80","spiceLevel":0,"status":"Ready","tagLine":"Spicy touch for your taste buds","updateDateTime":"2022-03-18T01:30:29.340584","inventory":8,"quantity":1}]}'

示例输出:

messageIds:
- '5063709859203105'

查看工作流执行详细信息和日志

1e802826c700cc3e

aad0eae7a970316.png

7. 工作流结构化日志记录

该工作流配置为以 JSON 格式写入结构化日志。日志使用 Cloud Logging API、workflows.googleapis.com/Workflow 资源在日志名称 projects/${PROJECT_ID}/logs/Workflows 下写入。

查看下面的日志记录配置。

    - log_totalAmount:
        call: sys.log
        args:
            json:
              orderNumber: ${order.orderNumber}
              totalAmount: ${totalAmount}
              multiplier: ${multiplier}
              totalRewardPoints: ${rewardPoints}
              orderRewardPoints: ${orderRewardPoints}
            severity: INFO

在控制台中打开日志浏览器,然后运行查询,以查找总金额超过 2 美元的已处理订单。

使用以下查询,将项目 ID(qwiklabs-gcp-01-1a990bfcadb3) 替换为当前的项目 ID:

resource.type="workflows.googleapis.com/Workflow" AND 
logName=projects/qwiklabs-gcp-01-1a990bfcadb3/logs/Workflows AND 
jsonPayload.totalAmount > 2 AND 
timestamp >= "2022-11-01T23:59:59Z" AND 
timestamp <= "2023-11-05T00:00:00Z"

示例输出:

22d2f4686c58724d.png

打开 Cloud Shell,然后使用以下命令通过 gcloud CLI 读取日志

将项目 ID(qwiklabs-gcp-01-1a990bfcadb3) 替换为当前的项目 ID。

gcloud logging read 'resource.type="workflows.googleapis.com/Workflow" AND logName=projects/qwiklabs-gcp-01-1a990bfcadb3/logs/Workflows AND jsonPayload.totalAmount > 2 AND timestamp >= "2022-11-01T23:59:59Z" AND timestamp <= "2023-11-05T00:00:00Z"' --limit 10 --format="table(jsonPayload.orderNumber,jsonPayload.totalAmount,jsonPayload.orderRewardPoints,jsonPayload.totalRewardPoints,jsonPayload.multiplier)"

使用 table 格式的输出示例:

35d5fd851ecde60.png

将项目 ID(qwiklabs-gcp-01-1a990bfcadb3) 替换为当前的项目 ID。

gcloud logging read 'resource.type="workflows.googleapis.com/Workflow" AND logName=projects/qwiklabs-gcp-01-1a990bfcadb3/logs/Workflows AND jsonPayload.totalAmount > 2 AND timestamp >= "2022-11-01T23:59:59Z" AND timestamp <= "2023-11-05T00:00:00Z"' --limit 10 --format=json | jq

使用 json 格式的输出示例:

ac7421548ea9a9f2.png

8. 查看客户记录

(可选步骤)目前,customer-service 配置为仅接受来自内部网络的流量。

运行以下命令以保存服务网址并调用客户服务。

export REGION=us-east1
CUSTOMER_SERVICE_URL=$(gcloud run services describe customer-service \
    --region=$REGION \
    --format=json | jq \
    --raw-output ".status.url")

curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" $CUSTOMER_SERVICE_URL/customer

您会收到一条错误消息,提示您访问权限已被禁止。

<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>403 Forbidden</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Forbidden</h1>
<h2>Access is forbidden.</h2>
<h2></h2>
</body></html>

如需查看现有客户记录,请将 Cloud Run customer-service ingress 设置更改为“Allow all traffic”选项,然后点击“保存”。

这会将端点设为公开,然后您可以使用 curl 从 Cloud Shell 调用 Customer Service API。

9156e0eb0a19bc68

运行以下命令以保存服务网址并列出现有客户。

CUSTOMER_SERVICE_URL=$(gcloud run services describe customer-service \
    --region=$REGION \
    --format=json | jq \
    --raw-output ".status.url")

curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" $CUSTOMER_SERVICE_URL/customer | jq

示例输出:

[
  {
    "id": "id1",
    "rewardPoints": 3,
    "address": "1845 Denise St",
    "city": "Mountain View",
    "createDateTime": "2022-11-11T15:56:45.487566",
    "email": "ajensen9090+eats@gmail.com",
    "name": "Angela Jensen",
    "state": "CA",
    "updateDateTime": "2022-11-11T15:56:45.866125",
    "zip": "94043"
  }
]

运行命令以多次发布新订单,并使用 curl 命令验证客户奖励积分。

发布新订单消息:

export TOPIC_ID=order-topic
gcloud pubsub topics publish $TOPIC_ID --message '{"userId":"id1","orderNumber":123456,"name":"Angela Jensen","email":"ajensen9090+eats@gmail.com","address":"1845 Denise St","city":"Mountain View","state":"CA","zip":"94043","orderItems":[{"id":7,"createDateTime":"2022-03-17T21:51:44.968584","itemImageURL":"https://images.unsplash.com/photo-1618449840665-9ed506d73a34?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80","itemName":"Curry Plate","itemPrice":12.5,"itemThumbnailURL":"https://images.unsplash.com/photo-1618449840665-9ed506d73a34?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80","spiceLevel":0,"status":"Ready","tagLine":"Spicy touch for your taste buds","updateDateTime":"2022-03-18T01:30:29.340584","inventory":8,"quantity":1}]}'

验证客户奖励积分:

curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" $CUSTOMER_SERVICE_URL/customer | jq

验证日志。将项目 ID(qwiklabs-gcp-01-1a990bfcadb3) 替换为当前的项目 ID。

gcloud logging read 'resource.type="workflows.googleapis.com/Workflow" AND logName=projects/qwiklabs-gcp-01-1a990bfcadb3/logs/Workflows AND jsonPayload.totalAmount > 2 AND timestamp >= "2022-11-01T23:59:59Z" AND timestamp <= "2023-11-05T00:00:00Z"' --limit 10 --format="table(jsonPayload.orderNumber,jsonPayload.totalAmount,jsonPayload.orderRewardPoints,jsonPayload.totalRewardPoints,jsonPayload.multiplier)"

9. 恭喜!

恭喜,您已完成此 Codelab!

所学内容:

  • 如何配置工作流
  • 如何为 Workflows 配置 Eventarc 触发器
  • 如何通过 Workflows 调用 Cloud Run 服务
  • 如何使用 gcloud CLI 在 Cloud Logging 中查询结构化日志

后续步骤:

探索其他 Cymbal Eats Codelab:

清理

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

删除项目

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