使用 Eventarc 触发工作流

1. 概览

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

c6d4337a47b55333.png

什么是 Eventarc?

借助 Eventarc,您可以构建事件驱动型架构,而无需实现、自定义或维护底层基础架构。Eventarc 提供了一个用于管理解耦的微服务之间的状态更改(称为“事件”)流的标准化解决方案。事件触发后,Eventarc 会通过 Pub/Sub 订阅将这些事件路由到各个目的地(例如工作流或 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 会为每个云项目、文件夹和组织提供管理员活动日志和数据访问审核日志。
  • 直接事件。Eventarc 可以由各种直接事件触发,例如更新 Cloud Storage 存储分区或更新 Firebase Remote Config 模板。

活动目的地

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

c7ca054200edf1b3.png

什么是 Workflows?

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

工作流应用场景:

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

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

工作流优势

  • 配置优于代码:通过将逻辑移至配置而非编写代码来减少技术债务。
  • 简化架构。有状态的工作流可让您直观呈现和监控复杂的服务集成,而无需额外的依赖项。
  • 整合可靠性和容错性。即使其他系统发生故障,也可以使用默认或自定义重试逻辑和错误处理来控制故障,通过为 Cloud Spanner 的每个步骤设置检查点,帮助您跟踪进度。
  • 零维护。按需扩缩:无需修补或维护。您只需在工作流运行时付费,等待或非活跃时无需付费。

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

学习内容

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

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

前提条件

  • 本实验假设您熟悉 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 客户服务 - 使用 Quarkus 框架的基于 Java 的微服务。
./lab-setup.sh

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

6356559df3eccdda.png

设置过程大约需要 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 CLI,通过 Google Cloud 控制台或命令行管理工作流。
  • 以编程方式 - Workflows API 的 Cloud 客户端库或 REST API 可用于管理工作流。
  • 已安排 - 您可以使用 Cloud Scheduler 按特定时间表运行工作流。

运行时实参

可通过在主工作流中添加 params 字段(放置在主块中)访问在运行时传递的数据。主块接受任何有效的 JSON 数据类型的单个实参。params 字段指定工作流用于存储您传入数据的变量。

Cloud Run 服务身份验证工作流

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

如需详细了解服务至服务身份验证,请查看相关文档。

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

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. 配置和部署工作流

设置环境变量:

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 服务
  • 调用 Logging API
  • 将消息发布到 Pub/Sub 主题
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.png

查看工作流方面的更改。添加了新触发器。

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.png

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

在控制台中打开Logs Explorer,然后运行查询,以查找总金额超过 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.png

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

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 服务
  • 如何在 Cloud Logging 中使用 gcloud CLI 查询结构化日志

后续步骤:

探索其他 Cymbal Eats Codelab:

清理

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

删除项目

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