Cloud Pub/Sub のチュートリアル(第 2 世代)


このシンプルなチュートリアルでは、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
  • Cloud Build
  • Pub/Sub
  • Artifact Registry
  • Eventarc
  • Cloud Logging

詳細については、Cloud Functions の料金をご覧ください。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. Cloud Functions, Cloud Build, Artifact Registry, Eventarc, Logging, and 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, Cloud Build, Artifact Registry, Eventarc, Logging, and Pub/Sub API を有効にします。

    API を有効にする

  10. Google Cloud CLI をインストールします。
  11. gcloud CLI を初期化するには:

    gcloud init
  12. gcloud CLI がすでにインストールされている場合は、次のコマンドを実行して更新します。

    gcloud components update
  13. 開発環境を準備します。

前提条件

Pub/Sub トピックを作成します。

gcloud pubsub topics create YOUR_TOPIC_NAME

これは、関数をデプロイする前に行う必須のステップです。Cloud Functions(第 2 世代)では、関数をデプロイするときに Pub/Sub トピックが自動的に作成されません。

アプリケーションの準備

  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/v2/helloPubSub/

    Python

    cd python-docs-samples/functions/v2/pubsub/

    Go

    cd golang-samples/functions/functionsv2/hellopubsub/

    Java

    cd java-docs-samples/functions/v2/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

    const functions = require('@google-cloud/functions-framework');
    
    // Register a CloudEvent callback with the Functions Framework that will
    // be executed when the Pub/Sub trigger topic receives a message.
    functions.cloudEvent('helloPubSub', cloudEvent => {
      // The Pub/Sub message is passed as the CloudEvent's data payload.
      const base64name = cloudEvent.data.message.data;
    
      const name = base64name
        ? Buffer.from(base64name, 'base64').toString()
        : 'World';
    
      console.log(`Hello, ${name}!`);
    });

    Python

    import base64
    
    from cloudevents.http import CloudEvent
    import functions_framework
    
    # Triggered from a message on a Cloud Pub/Sub topic.
    @functions_framework.cloud_event
    def subscribe(cloud_event: CloudEvent) -> None:
        # Print out the data from Pub/Sub, to prove that it worked
        print(
            "Hello, " + base64.b64decode(cloud_event.data["message"]["data"]).decode() + "!"
        )
    
    

    Go

    
    // Package helloworld provides a set of Cloud Functions samples.
    package helloworld
    
    import (
    	"context"
    	"fmt"
    	"log"
    
    	"github.com/GoogleCloudPlatform/functions-framework-go/functions"
    	"github.com/cloudevents/sdk-go/v2/event"
    )
    
    func init() {
    	functions.CloudEvent("HelloPubSub", helloPubSub)
    }
    
    // MessagePublishedData contains the full Pub/Sub message
    // See the documentation for more details:
    // https://cloud.google.com/eventarc/docs/cloudevents#pubsub
    type MessagePublishedData struct {
    	Message PubSubMessage
    }
    
    // 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 CloudEvent message and extracts the Pub/Sub message.
    func helloPubSub(ctx context.Context, e event.Event) error {
    	var msg MessagePublishedData
    	if err := e.DataAs(&msg); err != nil {
    		return fmt.Errorf("event.DataAs: %w", err)
    	}
    
    	name := string(msg.Message.Data) // Automatically decoded from base64.
    	if name == "" {
    		name = "World"
    	}
    	log.Printf("Hello, %s!", name)
    	return nil
    }
    

    Java

    import com.google.cloud.functions.CloudEventsFunction;
    import com.google.gson.Gson;
    import functions.eventpojos.PubSubBody;
    import io.cloudevents.CloudEvent;
    import java.nio.charset.StandardCharsets;
    import java.util.Base64;
    import java.util.logging.Logger;
    
    public class SubscribeToTopic implements CloudEventsFunction {
      private static final Logger logger = Logger.getLogger(SubscribeToTopic.class.getName());
    
      @Override
      public void accept(CloudEvent event) {
        // The Pub/Sub message is passed as the CloudEvent's data payload.
        if (event.getData() != null) {
          // Extract Cloud Event data and convert to PubSubBody
          String cloudEventData = new String(event.getData().toBytes(), StandardCharsets.UTF_8);
          Gson gson = new Gson();
          PubSubBody body = gson.fromJson(cloudEventData, PubSubBody.class);
          // Retrieve and decode PubSub message data
          String encodedData = body.getMessage().getData();
          String decodedData =
              new String(Base64.getDecoder().decode(encodedData), StandardCharsets.UTF_8);
          logger.info("Hello, " + decodedData + "!");
        }
      }
    }

    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 nodejs-pubsub-function \
--gen2 \
--runtime=nodejs20 \
--region=REGION \
--source=. \
--entry-point=helloPubSub \
--trigger-topic=YOUR_TOPIC_NAME

サポートされている Node.js バージョンのランタイム ID を指定して関数を実行するには、--runtime フラグを使用します。

Python

gcloud functions deploy python-pubsub-function \
--gen2 \
--runtime=python312 \
--region=REGION \
--source=. \
--entry-point=subscribe \
--trigger-topic=YOUR_TOPIC_NAME

サポートされている Python バージョンのランタイム ID を指定して関数を実行するには、--runtime フラグを使用します。

Go

gcloud functions deploy go-pubsub-function \
--gen2 \
--runtime=go121 \
--region=REGION \
--source=. \
--entry-point=HelloPubSub \
--trigger-topic=YOUR_TOPIC_NAME

サポートされている Go バージョンのランタイム ID を指定して関数を実行するには、--runtime フラグを使用します。

Java

gcloud functions deploy java-pubsub-function \
--gen2 \
--runtime=java17 \
--region=REGION \
--source=. \
--entry-point=functions.SubscribeToTopic \
--memory=512MB \
--trigger-topic=YOUR_TOPIC_NAME

サポートされている Java バージョンのランタイム ID を指定して関数を実行するには、--runtime フラグを使用します。

C#

gcloud functions deploy csharp-pubsub-function \
--gen2 \
--runtime=dotnet6 \
--region=REGION \
--source=. \
--entry-point=HelloPubSub.Function \
--trigger-topic=YOUR_TOPIC_NAME

サポートされている .NET バージョンのランタイム ID を指定して関数を実行するには、--runtime フラグを使用します。

Ruby

gcloud functions deploy ruby-pubsub-function \
--gen2 \
--runtime=ruby32 \
--region=REGION \
--source=. \
--entry-point=hello_pubsub \
--trigger-topic=YOUR_TOPIC_NAME

サポートされている Ruby バージョンのランタイム ID を指定して関数を実行するには、--runtime フラグを使用します。

PHP

gcloud functions deploy php-pubsub-function \
--gen2 \
--runtime=php82 \
--region=REGION \
--source=. \
--entry-point=helloworldPubsub \
--trigger-topic=YOUR_TOPIC_NAME

サポートされている PHP バージョンのランタイム ID を指定して関数を実行するには、--runtime フラグを使用します。

ここで、YOUR_TOPIC_NAME は関数の登録先となる Pub/Sub トピックの名前です。

deploy コマンドを実行する前に、Google Cloud コンソールまたは gcloud コマンドライン ツールを使用して、トピックを作成する必要があります。Cloud Functions(第 1 世代)とは異なり、Cloud Functions(第 2 世代)では、Pub/Sub トリガーを使用して関数をデプロイするときに、Pub/Sub トピックが自動的に作成されません。

関数のトリガー

Pub/Sub 関数をテストするには:

  1. トピックにメッセージをパブリッシュします。

    gcloud pubsub topics publish my-topic --message="Friend"
    
  2. 関数のログを読み、結果を確認します。

    gcloud functions logs read \
      --gen2 \
      --region=REGION \
      --limit=5 \
      FUNCTION_NAME
    

    次のように置き換えます。

    • REGION は、関数をデプロイした Google Cloud リージョンの名前です(例: us-west1)。
    • FUNCTION_NAME は、デプロイ時に関数に指定した名前です(たとえば、このチュートリアルの Node.js 関数は関数名 nodejs-pubsub-function でデプロイされます)。

    ログの出力に、新しい「Friend」メッセージが含まれているはずです。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

プロジェクトの削除

課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. Google Cloud コンソールで、[リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

Cloud Functions の関数の削除

Cloud Functions を削除しても、Cloud Storage に保存されたリソースは削除されません。

このチュートリアルで作成した Cloud Functions の関数を削除するには、次のコマンドを実行します。

Node.js

gcloud functions delete nodejs-pubsub-function --gen2 --region REGION 

Python

gcloud functions delete python-pubsub-function --gen2 --region REGION 

Go

gcloud functions delete go-pubsub-function --gen2 --region REGION 

Java

gcloud functions delete java-pubsub-function --gen2 --region REGION 

C#

gcloud functions delete csharp-pubsub-function --gen2 --region REGION 

Ruby

gcloud functions delete ruby-pubsub-function --gen2 --region REGION 

PHP

gcloud functions delete php-pubsub-function --gen2 --region REGION 

Google Cloud Console から Cloud Functions を削除することもできます。