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. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  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 を削除することもできます。