1. 简介

您可以使用 Workflows 创建无服务器工作流,以按照您定义的顺序将一系列无服务器任务关联起来。您可以搭配使用 Google Cloud API 和无服务器函数(如 Cloud Functions 和 Cloud Run)的强大功能,调用外部 API 以创建灵活的无服务器应用。
工作流不需要进行基础架构管理,并且可以无缝地按需扩缩,包括缩减至零。由于采用的是按用量付费价格模式,您只需为执行时间付费。
在此 Codelab 中,您将学习如何使用 Workflows 连接各种 Google Cloud 服务和外部 HTTP API。具体来说,您将把两项公共 Cloud Functions 服务、一项专用 Cloud Run 服务和一个外部公共 HTTP API 连接到工作流中。
学习内容
- 工作流基础知识。
- 如何将公共 Cloud Functions 与 Workflows 关联。
- 如何将专用 Cloud Run 服务与 Workflows 连接起来。
- 如何使用 Workflows 连接外部 HTTP API。
2. 设置和要求
自定进度的环境设置
请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID。
- 接下来,您需要在 Cloud 控制台中启用结算功能,才能使用 Google Cloud 资源。
运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。请务必按照“清理”部分中的所有说明操作,该部分介绍了如何关停资源,以免产生超出本教程范围的结算费用。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。
启动 Cloud Shell
虽然可以通过笔记本电脑对 Google Cloud 进行远程操作,但在此 Codelab 中,您将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。
在 GCP 控制台中,点击右上角工具栏上的 Cloud Shell 图标:
预配和连接到环境应该只需要片刻时间。完成后,您应该会看到如下内容:
这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证功能。只需一个浏览器,即可完成本实验中的所有工作。
3. 工作流概览
基础知识
工作流由一系列使用基于 YAML 的 Workflows 语法描述的步骤组成。这是工作流的定义。如需详细了解 Workflows YAML 语法,请参阅语法参考页面。
工作流创建完毕后即会进行部署,这样工作流便可以执行。执行是指单次运行工作流定义中包含的逻辑。所有工作流都会独立执行,并且该产品支持大量并发执行。
启用服务
在此 Codelab 中,您将把 Cloud Functions、Cloud Run 服务与 Workflows 连接起来。您还将在构建服务期间使用 Cloud Build 和 Cloud Storage。
启用所有必要的服务:
gcloud services enable \ cloudfunctions.googleapis.com \ run.googleapis.com \ workflows.googleapis.com \ cloudbuild.googleapis.com \ storage.googleapis.com
在下一步中,您将在工作流中将两个 Cloud Functions 函数连接在一起。
4. 部署第一个 Cloud Functions 函数
第一个函数是 Python 中的随机数生成器。
创建并前往函数代码的目录:
mkdir ~/randomgen cd ~/randomgen
在目录中创建一个 main.py 文件,其中包含以下内容:
import random, json
from flask import jsonify
def randomgen(request):
randomNum = random.randint(1,100)
output = {"random":randomNum}
return jsonify(output)
当此函数收到 HTTP 请求时,它会生成一个介于 1 到 100 之间的随机数字,然后以 JSON 格式返回给调用方。
该函数依赖于 Flask 进行 HTTP 处理,因此我们需要将其添加为依赖项。Python 依赖项可通过 pip 进行管理,并在名为 requirements.txt 的元数据文件中表示。
在同一目录中创建一个包含以下内容的 requirements.txt 文件:
flask>=1.0.2
使用 HTTP 触发器部署函数,并允许未经身份验证的请求,请运行以下命令:
gcloud functions deploy randomgen \
--runtime python312 \
--trigger-http \
--allow-unauthenticated
部署函数后,您可以在控制台中显示的 url 属性下或使用 gcloud functions describe 命令查看该函数的网址。
您还可以使用以下 curl 命令访问该函数的网址:
curl $(gcloud functions describe randomgen --format='value(url)')
该函数已可用于工作流。
5. 部署第二个 Cloud Functions 函数
第二个函数是乘数。它将接收到的输入值乘以 2。
创建并前往函数代码的目录:
mkdir ~/multiply cd ~/multiply
在目录中创建一个 main.py 文件,其中包含以下内容:
import random, json
from flask import jsonify
def multiply(request):
request_json = request.get_json()
output = {"multiplied":2*request_json['input']}
return jsonify(output)
当此函数收到 HTTP 请求时,它会从 JSON 正文中提取 input,将其乘以 2,然后以 JSON 格式返回给调用方。
在同一目录中创建相同的 requirements.txt 文件,其中包含以下内容:
flask>=1.0.2
使用 HTTP 触发器部署函数,并允许未经身份验证的请求,请运行以下命令:
gcloud functions deploy multiply \
--runtime python312 \
--trigger-http \
--allow-unauthenticated
部署函数后,您还可以使用以下 curl 命令访问该函数的网址:
curl $(gcloud functions describe multiply --format='value(url)') \
-X POST \
-H "content-type: application/json" \
-d '{"input": 5}'
该函数已可用于工作流。
6. 连接两个 Cloud Functions
在第一个工作流中,将这两个函数连接在一起。
创建一个包含以下内容的 workflow.yaml 文件。
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- returnResult:
return: ${multiplyResult}
在此工作流中,您将从第一个函数获取一个随机数字,然后将其传递给第二个函数。结果是相乘后的随机数。
部署第一个工作流:
gcloud workflows deploy workflow --source=workflow.yaml
执行第一个工作流:
gcloud workflows execute workflow
工作流执行完毕后,您可以通过传入上一步中给出的执行 ID 来查看结果:
gcloud workflows executions describe <your-execution-id> --workflow workflow
输出将包含 result 和 state:
result: '{"body":{"multiplied":108},"code":200 ... }
...
state: SUCCEEDED
7. 连接外部 HTTP API
接下来,您将在工作流中将 math.js 连接为外部服务。
在 math.js 中,您可以按如下方式评估数学表达式:
curl https://api.mathjs.org/v4/?'expr=log(56)'
这次,您将使用 Cloud 控制台更新工作流。在 Google Cloud 控制台中找到 Workflows:

找到相应工作流,然后点击 Definition 标签页:

修改工作流定义,并添加对 math.js 的调用。
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- logFunction:
call: http.get
args:
url: https://api.mathjs.org/v4/
query:
expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
result: logResult
- returnResult:
return: ${logResult}
工作流现在将 multiply 函数的输出馈送到 math.js 中的 log 函数调用中。
界面会引导您编辑和部署工作流。部署完成后,点击 Execute 以执行工作流。您会看到执行的详细信息:

请注意状态代码 200 和包含日志函数输出的 body。
您刚刚将外部服务集成到我们的工作流程中,太棒了!
8. 部署 Cloud Run 服务
在最后一部分中,通过调用私有 Cloud Run 服务来完成工作流。这意味着,工作流需要经过身份验证才能调用 Cloud Run 服务。
Cloud Run 服务会返回传入数字的 math.floor。
创建并前往服务代码目录:
mkdir ~/floor cd ~/floor
在目录中创建一个 app.py 文件,其中包含以下内容:
import json
import logging
import os
import math
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['POST'])
def handle_post():
content = json.loads(request.data)
input = float(content['input'])
return f"{math.floor(input)}", 200
if __name__ != '__main__':
# Redirect Flask logs to Gunicorn logs
gunicorn_logger = logging.getLogger('gunicorn.error')
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
app.logger.info('Service started...')
else:
app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
Cloud Run 会部署容器,因此您需要一个 Dockerfile,并且您的容器需要绑定到 0.0.0.0 和 PORT 环境变量,因此需要使用上述代码。
当此函数收到 HTTP 请求时,它会从 JSON 正文中提取 input,调用 math.floor 并将结果返回给调用方。
在同一目录中,创建以下 Dockerfile:
# Use an official lightweight Python image. # https://hub.docker.com/_/python FROM python:3.7-slim # Install production dependencies. RUN pip install Flask gunicorn # Copy local code to the container image. WORKDIR /app COPY . . # Run the web service on container startup. Here we use the gunicorn # webserver, with one worker process and 8 threads. # For environments with multiple CPU cores, increase the number of workers # to be equal to the cores available. CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app
构建容器。
export SERVICE_NAME=floor
gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
容器构建完成后,将其部署到 Cloud Run。请注意 no-allow-unauthenticated 标志。这可确保服务仅接受经过身份验证的调用:
gcloud run deploy ${SERVICE_NAME} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
--platform managed \
--no-allow-unauthenticated
部署完成后,服务即可用于工作流。
9. 连接 Cloud Run 服务
在配置 Workflows 以调用私有 Cloud Run 服务之前,您需要先为 Workflows 创建一个服务账号,以供使用:
export SERVICE_ACCOUNT=workflows-sa
gcloud iam service-accounts create ${SERVICE_ACCOUNT}
向服务账号授予 run.invoker 角色。这样一来,服务账号便可调用经过身份验证的 Cloud Run 服务:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
--role "roles/run.invoker"
更新 workflow.yaml 中的工作流定义,以包含 Cloud Run 服务。请注意,您还包含 auth 字段,以确保 Workflows 在其对 Cloud Run 服务的调用中传递身份验证令牌:
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- logFunction:
call: http.get
args:
url: https://api.mathjs.org/v4/
query:
expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
result: logResult
- floorFunction:
call: http.post
args:
url: https://floor-<random-hash>.run.app
auth:
type: OIDC
body:
input: ${logResult.body}
result: floorResult
- returnResult:
return: ${floorResult}
更新工作流。这次传入服务账号:
gcloud workflows deploy workflow \
--source=workflow.yaml \
--service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
执行工作流:
gcloud workflows execute workflow
几秒钟后,您可以查看工作流执行情况,了解结果:
gcloud workflows executions describe <your-execution-id> --workflow workflow
输出将包含整数 result 和 state:
result: '{"body":"5","code":200 ... }
...
state: SUCCEEDED
10. 恭喜!
恭喜您完成此 Codelab。
所学内容
- 工作流基础知识。
- 如何将公共 Cloud Functions 与 Workflows 关联。
- 如何将专用 Cloud Run 服务与 Workflows 连接起来。
- 如何使用 Workflows 连接外部 HTTP API。