C# 中的 Google Cloud Functions 函数

使用 C# 编写 Google Cloud Functions 函数

关于此 Codelab

subject上次更新时间:10月 7, 2024
account_circleMete Atamel 编写

1. 简介

Google Cloud Run 函数是一个事件驱动型无服务器计算平台,借助 Cloud Run 函数,您可以编写代码,而无需担心预配资源或扩缩以应对不断变化的要求。

Cloud Run 函数有两种类型:

  • HTTP 函数会响应 HTTP 请求。
  • 事件函数由事件触发,例如有消息发布到 Cloud Pub/Sub 或有文件上传到 Cloud Storage

efb3268e3b74ed4f.png

本 Codelab 将引导您使用 C# 创建自己的 Cloud Run 函数。具体而言,您将部署 C# 函数来响应来自各种 Google Cloud 来源的 HTTP 和 CloudEvent。

学习内容

  • .NET 版 Functions 框架。
  • 如何编写 HTTP 函数。
  • 如何编写响应 Cloud Storage 事件的事件触发型函数。
  • 如何编写响应 Cloud Pub/Sub 事件的事件触发型函数。
  • 如何编写响应任何类型事件的事件触发型函数。

2. 设置和要求

自定进度的环境设置

  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

虽然可以通过笔记本电脑对 Google Cloud 进行远程操作,但在此 Codelab 中,您将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。

Google Cloud 控制台 中,点击右上角工具栏中的 Cloud Shell 图标:

55efc1aaa7a4d3ad.png

预配和连接到环境应该只需要片刻时间。完成后,您应该会看到如下内容:

7ffe5cbb04455448.png

这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5 GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证功能。您在此 Codelab 中的所有工作都可以在浏览器中完成。您无需安装任何程序。

3. 准备工作

在 Cloud Shell 中,运行以下命令以启用所需的服务:

gcloud services enable \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  cloudfunctions.googleapis.com \
  eventarc.googleapis.com \
  run.googleapis.com

接下来,设置您的地区。

REGION=<YOUR_REGION>

在本 Codelab 中,您将创建一个具有所需 Eventarc 权限和 Cloud Run Invoker 角色的服务账号,以便从 Cloud Storage 接收事件并调用 Cloud Run 函数。

首先,创建服务账号。

PROJECT_ID=$(gcloud config get-value core/project)
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')

SERVICE_ACCOUNT="cloud-run-functions"
SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com

gcloud iam service-accounts create $SERVICE_ACCOUNT \
  --display-name="Cloud Run functions Eventarc service account"

接下来,将项目的 Eventarc Event Receiver 角色 (roles/eventarc.eventReceiver) 授予与您的 Eventarc 触发器关联的服务账号,以便该触发器可以接收来自事件提供程序的事件。

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role=roles/eventarc.eventReceiver

然后,向服务账号授予 Cloud Run Invoker 角色,以便其可以调用函数。

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role=roles/run.invoker

4. .NET 版 Functions 框架

适用于 .NET 的 Functions 框架是一个开源 FaaS(函数即服务)框架,用于编写可移植的 .NET 函数。此框架由 Google Cloud Functions 团队提供。

借助 Cloud Functions 框架,您可以编写在许多不同环境中运行的轻量级函数,这些环境包括:

  • Google Cloud Run functions
  • 您的本地开发机器
  • Cloud Run 和 Cloud Run on GKE
  • 基于 Knative 的环境

在本 Codelab 中,您将使用适用于 .NET 的 Functions 框架及其模板,以 C# 语言创建和部署 Cloud Functions 函数。

在 Cloud Shell 中,运行以下命令以安装适用于 dotnet 的 Cloud Functions 模板:

dotnet new install Google.Cloud.Functions.Templates

这会为 dotnet 安装 3 个模板。每个模板均提供 C#、F# 和 VB 版本(但您在本实验中只会使用 C#)。您可以通过运行以下命令来验证模板是否已安装:

dotnet new list

Templates                                                 Short Name            
-----------------------------------------------------------------------
Google Cloud Functions CloudEvent Function                gcf-event
Google Cloud Functions CloudEvent Function (Untyped)      gcf-untyped-event
Google Cloud Functions HttpFunction                       gcf-http

5. HTTP 函数

您将创建和部署一个 HTTP 函数来响应 HTTP 请求。

使用 gcf-http 模板创建 HTTP 函数:

mkdir HelloHttp
cd HelloHttp
dotnet new gcf-http

这会创建一个项目和一个用于响应 HTTP 请求的 Function.cs 文件。

.csproj 文件中将目标框架更改为 net8.0

<TargetFramework>net8.0</TargetFramework>

如需将 Cloud Run 函数直接部署到 Cloud Run,请运行以下命令:

gcloud beta run deploy hello-http-function \
    --source . \
    --function HelloHttp.Function \
    --base-image dotnet8 \
    --region $REGION \
    --allow-unauthenticated

如果您想以 Cloud Functions (第 2 代) 的形式进行部署,请使用以下命令:

gcloud functions deploy hello-http-function \
    --allow-unauthenticated \
    --entry-point HelloHttp.Function \
    --gen2 \
    --region $REGION \
    --runtime dotnet8 \
    --trigger-http

函数部署完毕后,您可以使用以下 curl 命令调用该函数:

SERVICE_URL=$(gcloud run services describe hello-http-function --platform managed --region $REGION --format 'value(status.url)')

curl $SERVICE_URL

6. CloudEvent 函数 - GCS

您将创建并部署一个 CloudEvent 函数来响应 Google Cloud Storage (GCS) 事件。

首先,创建一个 Cloud Storage 存储分区。您稍后将从该存储分区监听事件:

BUCKET_NAME="cloud-functions-bucket-${PROJECT_ID}"
gsutil mb -l us-central1 gs://${BUCKET_NAME}

使用 gcf-event 模板创建 CloudEvent 函数:

cd ..
mkdir HelloGcs
cd HelloGcs
dotnet new gcf-event

这会创建一个项目和一个响应 CloudEvent 请求的 Function.cs 文件。它还会将 CloudEvent 的数据解析为 StorageObjectData

.csproj 文件中将目标框架更改为 net8.0

<TargetFramework>net8.0</TargetFramework>

如需将 Cloud Run 函数直接部署到 Cloud Run,您需要先部署该函数,然后为其创建触发器。

gcloud beta run deploy hello-gcs-function \
      --source . \
      --function HelloGcs.Function \
      --region $REGION \
      --base-image dotnet8 \
      --no-allow-unauthenticated

现在,为 Cloud Run 函数创建触发器

BUCKET_REGION=$REGION

gcloud eventarc triggers create hello-gcs-function-trigger \
     --location=$REGION \
     --destination-run-service=hello-gcs-function \
    --destination-run-region=$BUCKET_REGION \
     --event-filters="type=google.cloud.storage.object.v1.finalized" \
     --event-filters="bucket=$BUCKET_NAME" \
     --service-account=$SERVICE_ACCOUNT_ADDRESS

如果您希望以 Cloud Functions 第 2 代函数的形式进行部署,可以使用以下命令使用 trigger-eventtrigger-resource 标志部署函数:

gcloud functions deploy hello-gcs-function \
    --allow-unauthenticated \
    --entry-point HelloGcs.Function \
    --gen2 \
    --region $REGION \
    --runtime dotnet8 \
    --trigger-event google.storage.object.finalize \
    --trigger-resource ${BUCKET_NAME} \
    --service-account=$SERVICE_ACCOUNT_ADDRESS

几分钟后,该函数应会显示在 Cloud 控制台中:

c28654d74bb31420.png

通过将文件上传到存储分区来触发函数:

echo "Hello from Storage" > random.txt
gsutil cp random.txt gs://${BUCKET_NAME}

通过查看日志,验证函数是否已触发:

对于 Cloud Run 函数,您可以运行以下命令:

gcloud logging read "resource.labels.service_name=hello-gcs-function AND textPayload: Name" --format=json

对于第 2 代函数,您可以运行以下命令:

gcloud functions logs read hello-gcs-function \
    --gen2 \
    --region us-central1

7. CloudEvent 函数 - Pub/Sub

您将创建并部署一个 CloudEvent 函数来响应 Cloud Pub/Sub 事件。

首先,创建一个将发出事件的 Cloud Pub/Sub 主题:

TOPIC_NAME=cloud-functions-topic
gcloud pubsub topics create ${TOPIC_NAME}

使用 gcf-event 模板创建 CloudEvent 函数:

cd ..
mkdir HelloPubSub
cd HelloPubSub
dotnet new gcf-event

这会创建一个项目和一个响应 CloudEvent 请求的 Function.cs 文件。它还会默认将 CloudEvent 的数据解析为 StorageObjectData

.csproj 文件中将目标框架更改为 net8.0

<TargetFramework>net8.0</TargetFramework>

StorageObjectData 更改为 MessagePublishedData 以解析 Pub/Sub 消息。将 Google.Events.Protobuf.Cloud.Storage.V1 更改为 Google.Events.Protobuf.Cloud.PubSub.V1

最后,您的函数应如下所示:

using CloudNative.CloudEvents;
using Google.Cloud.Functions.Framework;
using Google.Events.Protobuf.Cloud.PubSub.V1;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace HelloPubSub;

public class Function : ICloudEventFunction<MessagePublishedData>
{
    public Task HandleAsync(CloudEvent cloudEvent, MessagePublishedData data, CancellationToken cancellationToken)
    {
        var nameFromMessage = data.Message?.TextData;
        var name = string.IsNullOrEmpty(nameFromMessage) ? "world" : nameFromMessage;
        Console.WriteLine($"Hello {name}");
        return Task.CompletedTask;
    }
}

如需将 Cloud Run 函数直接部署到 Cloud Run,您需要先部署该函数,然后为其创建触发器。

gcloud beta run deploy hello-pubsub-function \
      --source . \
      --function HelloPubSub.Function \
      --region $REGION \
      --base-image dotnet8 \
      --no-allow-unauthenticated \
      --service-account=$SERVICE_ACCOUNT_ADDRESS

现在,为 Cloud Run 函数创建触发器

gcloud eventarc triggers create my-pubsub-trigger \
    --location=$REGION \
    --service-account=$SERVICE_ACCOUNT_ADDRESS \
    --destination-run-service=hello-pubsub-function \
    --destination-run-region=$REGION \
    --destination-run-path="/" \
    --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
    --transport-topic=projects/$PROJECT_ID/topics/$TOPIC_NAME

如果您希望以 Cloud Functions 第 2 代函数的形式进行部署,可以使用以下命令使用 trigger-topic 标志部署函数:

gcloud functions deploy hello-pubsub-function \
    --allow-unauthenticated \
    --entry-point HelloPubSub.Function \
    --gen2 \
    --region us-central1 \
    --runtime dotnet8 \
    --trigger-topic ${TOPIC_NAME}

几分钟后,该函数应会显示在 Cloud 控制台中:

3443808da7caf3bc.png

向以下主题发布消息以触发函数:

gcloud pubsub topics publish ${TOPIC_NAME} --message="World"

通过查看日志,验证函数是否已触发。

对于 Cloud Run 函数,您可以运行以下命令:

gcloud logging read "resource.labels.service_name=hello-pubsub-function AND textPayload: World" --format=json

对于第 2 代函数,您可以运行以下命令:

gcloud functions logs read hello-pubsub-function \
    --gen2 \
    --region us-central1

8. CloudEvent 函数 - 无类型

如果您正在实验 CloudEvents,并且尚未确定要提交的数据载荷模型,或者希望函数能够处理任何 Cloud Event,则可以使用无类型的 CloudEvent 函数。

使用 gcf-untyped-event 模板创建 CloudEvent 函数:

cd ..
mkdir HelloUntyped
cd HelloUntyped
dotnet new gcf-untyped-event

这会创建一个项目和一个 Function.cs 文件,用于响应 CloudEvent 请求,而不会尝试解析 CloudEvent 的数据。

.csproj 文件中将目标框架更改为 net8.0

<TargetFramework>net8.0</TargetFramework>

如需将 Cloud Run 函数直接部署到 Cloud Run,您需要先部署该函数,然后为其创建触发器。

gcloud beta run deploy hello-untyped-function \
      --source . \
      --function HelloUntyped.Function \
      --region $REGION \
      --base-image dotnet8 \
      --no-allow-unauthenticated

现在,为 Cloud Run 函数创建触发器

BUCKET_REGION=$REGION

gcloud eventarc triggers create hello-untyped-function-trigger \
     --location=$REGION \
     --destination-run-service=hello-untyped-function \
    --destination-run-region=$BUCKET_REGION \
     --event-filters="type=google.cloud.storage.object.v1.finalized" \
     --event-filters="bucket=$BUCKET_NAME" \
     --service-account=$SERVICE_ACCOUNT_ADDRESS

如果您希望以 Cloud Functions 第 2 代函数的形式进行部署,可以使用以下命令使用 trigger-eventtrigger-resource 标志部署函数:

gcloud functions deploy hello-untyped-function \
    --allow-unauthenticated \
    --entry-point HelloUntyped.Function \
    --gen2 \
    --region us-central1 \
    --runtime dotnet8 \
    --trigger-event google.storage.object.finalize \
    --trigger-resource ${BUCKET_NAME}

当有文件上传到存储分区时,该函数将触发。

几分钟后,该函数应会显示在 Cloud 控制台中:

afe56530826787c6.png

通过将文件上传到存储分区来触发函数:

echo "Hello from Storage" > random.txt
gsutil cp random.txt gs://${BUCKET_NAME}

通过查看日志,验证函数是否已触发。

对于 Cloud Run 函数,您可以运行以下命令:

gcloud logging read "resource.labels.service_name=hello-gcs-function AND textPayload: Name" --format=json

对于第 2 代函数,您可以运行以下命令:

gcloud functions logs read hello-untyped-function \
    --gen2 \
    --region us-central1

9. 恭喜!

恭喜您完成此 Codelab。

所学内容

  • .NET 版 Functions 框架。
  • 如何编写 HTTP Cloud Functions 函数。
  • 如何编写响应 Cloud Storage 事件的 CloudEvent 函数。
  • 如何编写响应 Cloud Pub/Sub 事件的 CloudEvent 函数。
  • 如何编写响应任何类型事件的 CloudEvent 函数。