Cloud Pub/Sub 教程(第 1 代)


本简易教程演示了如何使用 Cloud Pub/Sub 触发器编写、部署和触发 Cloud Functions 事件驱动函数

如果您刚接触 Pub/Sub,并且希望了解详情,请参阅 Pub/Sub 文档,特别是管理主题和订阅。如需简要了解如何在 Cloud Functions 中处理 Pub/Sub 主题和订阅,请参阅 Google Cloud Pub/Sub 触发器

如果您要查找使用 Pub/Sub 本身的代码示例,请访问 Google Cloud 示例浏览器

目标

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

  • Cloud Functions
  • Pub/Sub

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

准备工作

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  3. 确保您的 Google Cloud 项目已启用结算功能

  4. 启用 Cloud Functions and Cloud Pub/Sub API。

    启用 API

  5. 安装 Google Cloud CLI。
  6. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  7. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  8. 确保您的 Google Cloud 项目已启用结算功能

  9. 启用 Cloud Functions and Cloud Pub/Sub API。

    启用 API

  10. 安装 Google Cloud CLI。
  11. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  12. 如果您已经安装 gcloud CLI,请运行以下命令进行更新:

    gcloud components update
  13. 准备开发环境。

准备应用

  1. 将示例应用代码库克隆到本地机器:

    Node.js

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

    或者,您也可以下载该示例的 zip 文件并将其解压缩。

    Python

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

    或者,您也可以下载该示例的 zip 文件并将其解压缩。

    Go

    git clone https://github.com/GoogleCloudPlatform/golang-samples.git

    或者,您也可以下载该示例的 zip 文件并将其解压缩。

    Java

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git

    或者,您也可以下载该示例的 zip 文件并将其解压缩。

    C#

    git clone https://github.com/GoogleCloudPlatform/dotnet-docs-samples.git

    或者,您也可以下载该示例的 zip 文件并将其解压缩。

    Ruby

    git clone https://github.com/GoogleCloudPlatform/ruby-docs-samples.git

    或者,您也可以下载该示例的 zip 文件并将其解压缩。

    PHP

    git clone https://github.com/GoogleCloudPlatform/php-docs-samples.git

    或者,您也可以下载该示例的 zip 文件并将其解压缩。

  2. 切换到包含用于访问 Pub/Sub 的 Cloud Functions 函数示例代码的目录:

    Node.js

    cd nodejs-docs-samples/functions/helloworld/

    Python

    cd python-docs-samples/functions/helloworld/

    Go

    cd golang-samples/functions/helloworld/

    Java

    cd java-docs-samples/functions/helloworld/hello-pubsub/

    C#

    cd dotnet-docs-samples/functions/helloworld/HelloPubSub/

    Ruby

    cd ruby-docs-samples/functions/helloworld/pubsub/

    PHP

    cd php-docs-samples/functions/helloworld_pubsub/

  3. 查看示例代码:

    Node.js

    /**
     * Background Cloud Function to be triggered by Pub/Sub.
     * This function is exported by index.js, and executed when
     * the trigger topic receives a message.
     *
     * @param {object} message The Pub/Sub message.
     * @param {object} context The event metadata.
     */
    exports.helloPubSub = (message, context) => {
      const name = message.data
        ? Buffer.from(message.data, 'base64').toString()
        : 'World';
    
      console.log(`Hello, ${name}!`);
    };

    Python

    def hello_pubsub(event, context):
        """Background Cloud Function to be triggered by Pub/Sub.
        Args:
             event (dict):  The dictionary with data specific to this type of
                            event. The `@type` field maps to
                             `type.googleapis.com/google.pubsub.v1.PubsubMessage`.
                            The `data` field maps to the PubsubMessage data
                            in a base64-encoded string. The `attributes` field maps
                            to the PubsubMessage attributes if any is present.
             context (google.cloud.functions.Context): Metadata of triggering event
                            including `event_id` which maps to the PubsubMessage
                            messageId, `timestamp` which maps to the PubsubMessage
                            publishTime, `event_type` which maps to
                            `google.pubsub.topic.publish`, and `resource` which is
                            a dictionary that describes the service API endpoint
                            pubsub.googleapis.com, the triggering topic's name, and
                            the triggering event type
                            `type.googleapis.com/google.pubsub.v1.PubsubMessage`.
        Returns:
            None. The output is written to Cloud Logging.
        """
        import base64
    
        print(
            """This Function was triggered by messageId {} published at {} to {}
        """.format(
                context.event_id, context.timestamp, context.resource["name"]
            )
        )
    
        if "data" in event:
            name = base64.b64decode(event["data"]).decode("utf-8")
        else:
            name = "World"
        print(f"Hello {name}!")
    
    

    Go

    
    // Package helloworld provides a set of Cloud Functions samples.
    package helloworld
    
    import (
    	"context"
    	"log"
    )
    
    // PubSubMessage is the payload of a Pub/Sub event.
    // See the documentation for more details:
    // https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage
    type PubSubMessage struct {
    	Data []byte `json:"data"`
    }
    
    // HelloPubSub consumes a Pub/Sub message.
    func HelloPubSub(ctx context.Context, m PubSubMessage) error {
    	name := string(m.Data) // Automatically decoded from base64.
    	if name == "" {
    		name = "World"
    	}
    	log.Printf("Hello, %s!", name)
    	return nil
    }
    

    Java

    
    import com.google.cloud.functions.BackgroundFunction;
    import com.google.cloud.functions.Context;
    import functions.eventpojos.PubsubMessage;
    import java.nio.charset.StandardCharsets;
    import java.util.Base64;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    public class HelloPubSub implements BackgroundFunction<PubsubMessage> {
      private static final Logger logger = Logger.getLogger(HelloPubSub.class.getName());
    
      @Override
      public void accept(PubsubMessage message, Context context) {
        String name = "world";
        if (message != null && message.getData() != null) {
          name = new String(
              Base64.getDecoder().decode(message.getData().getBytes(StandardCharsets.UTF_8)),
              StandardCharsets.UTF_8);
        }
        logger.info(String.format("Hello %s!", name));
        return;
      }
    }

    C#

    using CloudNative.CloudEvents;
    using Google.Cloud.Functions.Framework;
    using Google.Events.Protobuf.Cloud.PubSub.V1;
    using Microsoft.Extensions.Logging;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace HelloPubSub;
    
    public class Function : ICloudEventFunction<MessagePublishedData>
    {
        private readonly ILogger _logger;
    
        public Function(ILogger<Function> logger) =>
            _logger = logger;
    
        public Task HandleAsync(CloudEvent cloudEvent, MessagePublishedData data, CancellationToken cancellationToken)
        {
            string nameFromMessage = data.Message?.TextData;
            string name = string.IsNullOrEmpty(nameFromMessage) ? "world" : nameFromMessage;
            _logger.LogInformation("Hello {name}", name);
            return Task.CompletedTask;
        }
    }

    Ruby

    require "functions_framework"
    require "base64"
    
    FunctionsFramework.cloud_event "hello_pubsub" do |event|
      # The event parameter is a CloudEvents::Event::V1 object.
      # See https://cloudevents.github.io/sdk-ruby/latest/CloudEvents/Event/V1.html
      name = Base64.decode64 event.data["message"]["data"] rescue "World"
    
      # A cloud_event function does not return a response, but you can log messages
      # or cause side effects such as sending additional events.
      logger.info "Hello, #{name}!"
    end

    PHP

    
    use CloudEvents\V1\CloudEventInterface;
    use Google\CloudFunctions\FunctionsFramework;
    
    // Register the function with Functions Framework.
    // This enables omitting the `FUNCTIONS_SIGNATURE_TYPE=cloudevent` environment
    // variable when deploying. The `FUNCTION_TARGET` environment variable should
    // match the first parameter.
    FunctionsFramework::cloudEvent('helloworldPubsub', 'helloworldPubsub');
    
    function helloworldPubsub(CloudEventInterface $event): void
    {
        $log = fopen(getenv('LOGGER_OUTPUT') ?: 'php://stderr', 'wb');
    
        $cloudEventData = $event->getData();
        $pubSubData = base64_decode($cloudEventData['message']['data']);
    
        $name = $pubSubData ? htmlspecialchars($pubSubData) : 'World';
        fwrite($log, "Hello, $name!" . PHP_EOL);
    }

部署函数

如需部署带有 Pub/Sub 触发器的函数,请在包含示例代码(如果是 Java,则为 pom.xml 文件)的目录中运行以下命令:

Node.js

gcloud functions deploy helloPubSub \
--runtime nodejs20 \
--trigger-topic YOUR_TOPIC_NAME

使用 --runtime 标志可以指定支持的 Node.js 版本的运行时 ID 来运行您的函数。

Python

gcloud functions deploy hello_pubsub \
--runtime python312 \
--trigger-topic YOUR_TOPIC_NAME

使用 --runtime 标志可以指定支持的 Python 版本的运行时 ID 来运行您的函数。

Go

gcloud functions deploy HelloPubSub \
--runtime go121 \
--trigger-topic YOUR_TOPIC_NAME

使用 --runtime 标志可以指定支持的 Go 版本的运行时 ID 来运行您的函数。

Java

gcloud functions deploy java-pubsub-function \
--entry-point functions.HelloPubSub \
--runtime java17 \
--memory 512MB \
--trigger-topic YOUR_TOPIC_NAME

使用 --runtime 标志可以指定支持的 Java 版本的运行时 ID 来运行您的函数。

C#

gcloud functions deploy csharp-pubsub-function \
--entry-point HelloPubSub.Function \
--runtime dotnet6 \
--trigger-topic YOUR_TOPIC_NAME

使用 --runtime 标志可以指定支持的 .NET 版本的运行时 ID 来运行您的函数。

Ruby

gcloud functions deploy hello_pubsub --runtime ruby32 \
--trigger-topic YOUR_TOPIC_NAME

使用 --runtime 标志可以指定支持的 Ruby 版本的运行时 ID 来运行您的函数。

PHP

 gcloud functions deploy helloworldPubsub --runtime php82 \
--trigger-topic YOUR_TOPIC_NAME

使用 --runtime 标志可以指定支持的 PHP 版本的运行时 ID 来运行您的函数。

其中,YOUR_TOPIC_NAME 是函数将订阅的 Pub/Sub 主题的名称。

如果 YOUR_TOPIC_NAME 不存在,则此命令会为您创建。您还可以在运行 deploy 命令之前,使用 Google Cloud 控制台或以下 gcloud 命令创建主题:

gcloud pubsub topics create YOUR_TOPIC_NAME

触发函数

  1. 向您的 Pub/Sub 主题发布消息。在此示例中,消息是函数将在问候语中使用的名称:

    gcloud pubsub topics publish YOUR_TOPIC_NAME --message YOUR_NAME

    请将 YOUR_TOPIC_NAME 替换为您的 Pub/Sub 主题的名称,并将 YOUR_NAME 替换为任意字符串。

  2. 检查日志以确保执行已完成:

    gcloud functions logs read --limit 50
    

您还可以从函数内部向 Pub/Sub 主题发布消息。

清除数据

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

删除项目

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

要删除项目,请执行以下操作:

  1. 在 Google Cloud 控制台中,进入管理资源页面。

    转到“管理资源”

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

删除 Cloud Functions 函数

删除 Cloud Functions 函数不会移除存储在 Cloud Storage 中的任何资源。

如需删除您在本教程中创建的 Cloud Functions 函数,请运行以下命令:

Node.js

gcloud functions delete helloPubSub 

Python

gcloud functions delete hello_pubsub 

Go

gcloud functions delete HelloPubSub 

Java

gcloud functions delete java-pubsub-function 

C#

gcloud functions delete csharp-pubsub-function 

Ruby

gcloud functions delete hello_pubsub 

PHP

gcloud functions delete helloworldPubsub 

您也可以通过 Google Cloud 控制台删除 Cloud Functions 函数。