关于此 Codelab
1. 简介
概览
Cloud Run functions 是 Google Cloud 的函数即服务产品,由 Cloud Run 和 Eventarc 提供支持,可让您对性能和可伸缩性进行更高级的控制,并更好地控制函数运行时和来自 90 多个事件来源的触发器。
本 Codelab 将引导您创建 Cloud Run 函数,以响应 HTTP 调用,并由 Pub/Sub 消息和 Cloud 审核日志触发。
此 Codelab 还会使用自动基础映像更新功能为函数部署指定基础映像,方法是使用 --base-image
标志。通过为 Cloud Run 配置自动基础映像更新,使 Google 能够自动为基础映像的操作系统和语言运行时组件打安全补丁。您无需重新构建或重新部署服务,即可更新基础映像。如需了解详情,请参阅自动基础映像更新
如果您不想使用自动基础映像更新,可以从此 Codelab 中显示的示例中移除 --base-image
标志。
学习内容
- Cloud Run functions 概览以及如何使用自动基础映像更新。
- 如何编写响应 HTTP 调用的函数。
- 如何编写响应 Pub/Sub 消息的函数。
- 如何编写响应 Cloud Storage 事件的函数。
- 如何在两个修订版本之间拆分流量。
- 如何通过实例数下限来避免冷启动。
2. 设置和要求
创建根文件夹
为所有示例创建一个根文件夹。
mkdir crf-codelab cd crf-codelab
设置环境变量
设置将在此 Codelab 中全程使用的环境变量。
gcloud config set project <YOUR-PROJECT-ID> REGION=<YOUR_REGION> PROJECT_ID=$(gcloud config get-value project)
启用 API
启用所有必要的服务:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ eventarc.googleapis.com \ run.googleapis.com \ logging.googleapis.com \ pubsub.googleapis.com
3. HTTP 函数
对于第一个函数,我们将创建一个用于响应 HTTP 请求的经过身份验证的 Node.js 函数。我们还将使用 10 分钟的超时时间来展示函数如何有更多时间响应 HTTP 请求。
创建
为应用创建一个文件夹,然后打开该文件夹:
mkdir hello-http cd hello-http
创建用于响应 HTTP 请求的 index.js
文件:
const functions = require('@google-cloud/functions-framework'); functions.http('helloWorld', (req, res) => { res.status(200).send('HTTP with Node.js in Cloud Run functions!'); });
创建一个 package.json
文件来指定依赖项:
{ "name": "nodejs-run-functions-codelab", "version": "0.0.1", "main": "index.js", "dependencies": { "@google-cloud/functions-framework": "^2.0.0" } }
部署
部署函数的方法如下:
gcloud run deploy nodejs-run-function \ --source . \ --function helloWorld \ --base-image nodejs22 \ --region $REGION \ --timeout 600 \ --no-allow-unauthenticated
此命令使用 buildpack 将函数源代码转换为可用于生产环境的容器映像。
请注意以下事项:
--source
标志用于指示 Cloud Run 将函数构建为基于可运行容器的服务--function
标志(新)用于将新服务的入口点设置为您要调用的函数签名--base-image
标志(新)用于指定函数的基础映像环境,例如nodejs22
、python312
、go123
、java21
、dotnet8
、ruby33
或php83
。如需详细了解基础映像以及每个映像中包含的软件包,请参阅运行时基础映像。- (可选)
--timeout
标志可让函数在响应 HTTP 请求时使用更长的超时时间。在此示例中,使用 600 秒来演示 10 分钟的响应时间。 - (可选)
--no-allow-unauthenticated
,用于防止函数被公开调用
测试
使用以下命令测试函数:
# get the Service URL SERVICE_URL="$(gcloud run services describe nodejs-run-function --region $REGION --format 'value(status.url)')" # invoke the service curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL
您应该会看到消息 HTTP with Node.js in Cloud Run functions!
作为响应。
4. Pub/Sub 函数
对于第二个函数,我们将创建一个由发布到特定主题的 Pub/Sub 消息触发的 Python 函数。
设置 Pub/Sub 身份验证令牌
如果您在 2021 年 4 月 8 日当天或之前启用了 Pub/Sub 服务账号,请将 iam.serviceAccountTokenCreator
角色授予 Pub/Sub 服务账号:
PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)') gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \ --role roles/iam.serviceAccountTokenCreator
创建
创建要用于示例的 Pub/Sub 主题:
TOPIC=cloud-run-functions-pubsub-topic gcloud pubsub topics create $TOPIC
为应用创建一个文件夹,然后打开该文件夹:
mkdir ../hello-pubsub cd ../hello-pubsub
创建一个 main.py
文件,用于记录包含 CloudEvent ID 的消息:
import functions_framework @functions_framework.cloud_event def hello_pubsub(cloud_event): print('Pub/Sub with Python in Cloud Run functions! Id: ' + cloud_event['id'])
创建一个包含以下内容的 requirements.txt
文件,以指定依赖项:
functions-framework==3.*
部署
部署函数的方法如下:
gcloud run deploy python-pubsub-function \ --source . \ --function hello_pubsub \ --base-image python313 \ --region $REGION \ --no-allow-unauthenticated
检索要用于服务账号身份的项目编号。
PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)')
创建触发器
gcloud eventarc triggers create python-pubsub-function-trigger \ --location=$REGION \ --destination-run-service=python-pubsub-function \ --destination-run-region=$REGION \ --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \ --transport-topic=projects/$PROJECT_ID/topics/$TOPIC \ --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com
测试
向该主题发送消息以测试函数:
gcloud pubsub topics publish $TOPIC --message="Hello World"
您应该会在日志中看到已接收到的 CloudEvent:
gcloud run services logs read python-pubsub-function --region $REGION --limit=10
5. Cloud Storage 函数
对于下一个函数,我们将创建一个 Node.js 函数来响应来自 Cloud Storage 存储分区的事件。
设置
如需使用 Cloud Storage 函数,请将 pubsub.publisher
IAM 角色授予 Cloud Storage 服务账号:
SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER) gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$SERVICE_ACCOUNT \ --role roles/pubsub.publisher
创建
为应用创建一个文件夹,然后打开该文件夹:
mkdir ../hello-storage cd ../hello-storage
创建一个仅响应 Cloud Storage 事件的 index.js
文件:
const functions = require('@google-cloud/functions-framework'); functions.cloudEvent('helloStorage', (cloudevent) => { console.log('Cloud Storage event with Node.js in Cloud Run functions!'); console.log(cloudevent); });
创建一个 package.json
文件来指定依赖项:
{ "name": "nodejs-crf-cloud-storage", "version": "0.0.1", "main": "index.js", "dependencies": { "@google-cloud/functions-framework": "^2.0.0" } }
部署
首先,创建一个 Cloud Storage 存储分区(或使用您已有的现有存储分区):
export BUCKET_NAME="gcf-storage-$PROJECT_ID" export BUCKET="gs://gcf-storage-$PROJECT_ID" gsutil mb -l $REGION $BUCKET
部署函数的方法如下:
gcloud run deploy nodejs-crf-cloud-storage \ --source . \ --base-image nodejs22 \ --function helloStorage \ --region $REGION \ --no-allow-unauthenticated
函数部署完毕后,您可以在 Cloud 控制台的 Cloud Run 部分下看到该函数。
现在,创建 Eventarc 触发器。
BUCKET_REGION=$REGION gcloud eventarc triggers create nodejs-crf-cloud-storage-trigger \ --location=$BUCKET_REGION \ --destination-run-service=nodejs-crf-cloud-storage \ --destination-run-region=$REGION \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=$BUCKET_NAME" \ --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com
测试
通过将文件上传到存储分区来测试函数:
echo "Hello World" > random.txt gsutil cp random.txt $BUCKET/random.txt
您应该会在日志中看到已接收到的 CloudEvent:
gcloud run services logs read nodejs-crf-cloud-storage --region $REGION --limit=10
6. 流量分配
Cloud Run functions 支持函数的多个修订版本,可在不同的修订版本之间拆分流量,还可将函数回滚到先前版本。
在此步骤中,您将部署一个函数的 2 个修订版本,然后在它们之间按 50-50 的比例拆分流量。
创建
为应用创建一个文件夹,然后打开该文件夹:
mkdir ../traffic-splitting cd ../traffic-splitting
创建一个 main.py
文件,并在其中添加一个 Python 函数,用于读取颜色环境变量,并以相应背景颜色的 Hello World
进行响应:
import os color = os.environ.get('COLOR') def hello_world(request): return f'<body style="background-color:{color}"><h1>Hello World!</h1></body>'
创建一个包含以下内容的 requirements.txt
文件,以指定依赖项:
functions-framework==3.*
部署
部署背景为橙色的函数的第一个修订版本:
COLOR=orange gcloud run deploy hello-world-colors \ --source . \ --base-image python313 \ --function hello_world \ --region $REGION \ --allow-unauthenticated \ --update-env-vars COLOR=$COLOR
此时,如果您通过在浏览器中查看 HTTP 触发器(上述部署命令的 URI 输出)来测试函数,则应该会看到背景为橙色的 Hello World
:
部署背景为黄色的第二个修订版本:
COLOR=yellow gcloud run deploy hello-world-colors \ --source . \ --base-image python313 \ --function hello_world \ --region $REGION \ --allow-unauthenticated \ --update-env-vars COLOR=$COLOR
由于这是最新修订版,因此如果您测试该函数,应该会看到背景为黄色的 Hello World
:
按 50-50 的比例分配流量
如需在橙色和黄色修订版本之间分配流量,您需要查找 Cloud Run 服务的修订版本 ID。以下是用于查看修订 ID 的命令:
gcloud run revisions list --service hello-world-colors \ --region $REGION --format 'value(REVISION)'
输出应类似如下所示:
hello-world-colors-00001-man hello-world-colors-00002-wok
现在,按如下方式在两个修订版本之间拆分流量(请根据您的修订版本名称更新 X-XXX
):
gcloud run services update-traffic hello-world-colors \ --region $REGION \ --to-revisions hello-world-colors-0000X-XXX=50,hello-world-colors-0000X-XXX=50
测试
访问函数的公共网址,以测试该函数。您应该会有一半的时间看到橙色修订版本,另一半时间看到黄色修订版本:
如需了解详情,请参阅回滚、逐步发布和流量迁移。
7. 实例数下限
在 Cloud Run 函数中,您可以指定要保持备用状态并且准备处理请求的函数实例数下限。这对于限制冷启动的次数非常有用。
在此步骤中,您将部署一个初始化缓慢的函数。您会观察到冷启动问题。然后,您将最小实例值设置为 1 来部署该函数,以消除冷启动。
创建
为应用创建一个文件夹,并打开该文件夹:
mkdir ../min-instances cd ../min-instances
创建 main.go
文件,此 Go 服务有一个 init
函数,该函数会休眠 10 秒以模拟长时间初始化。它还包含一个用于响应 HTTP 调用的 HelloWorld
函数:
package p import ( "fmt" "net/http" "time" ) func init() { time.Sleep(10 * time.Second) } func HelloWorld(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Slow HTTP Go in Cloud Run functions!") }
部署
使用默认的最小实例值 0 部署函数的第一个修订版本:
gcloud run deploy go-slow-function \ --source . \ --base-image go123 \ --function HelloWorld \ --region $REGION \ --no-allow-unauthenticated
使用以下命令测试函数:
# get the Service URL SERVICE_URL="$(gcloud run services describe go-slow-function --region $REGION --format 'value(status.url)')" # invoke the service curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL
您会发现第一次调用会出现 10 秒的延迟(冷启动),然后看到消息。后续调用应立即返回。
设置实例数下限
如需消除首次请求时的冷启动,请将 --min-instances
标志设置为 1,然后重新部署函数,如下所示:
gcloud run deploy go-slow-function \ --source . \ --base-image go123 \ --function HelloWorld \ --region $REGION \ --no-allow-unauthenticated \ --min-instances 1
测试
再次测试该函数:
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL
您应该不会再在第一个请求中看到 10 秒的延迟。由于实例数下限,首次调用(在很长一段时间没有调用后)的冷启动问题已消失!
如需了解详情,请参阅使用实例数下限。
8. 恭喜!
恭喜您完成此 Codelab!
所学内容
- Cloud Run functions 概览以及如何使用自动基础映像更新。
- 如何编写响应 HTTP 调用的函数。
- 如何编写响应 Pub/Sub 消息的函数。
- 如何编写响应 Cloud Storage 事件的函数。
- 如何在两个修订版本之间拆分流量。
- 如何通过实例数下限来避免冷启动。