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. Cloud プロジェクトに対して課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。

  4. Cloud Functions, Cloud Build, Artifact Registry, Eventarc, Logging, and Pub/Sub API を有効にします。

    API を有効にする

  5. Google Cloud CLI をインストールして初期化します。
  6. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

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

  7. Cloud プロジェクトに対して課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。

  8. Cloud Functions, Cloud Build, Artifact Registry, Eventarc, Logging, and Pub/Sub API を有効にします。

    API を有効にする

  9. Google Cloud CLI をインストールして初期化します。
  10. gcloud CLI がすでにインストールされている場合は、次のコマンドを実行して更新します。

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

前提条件

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
    
    import functions_framework
    
    # Triggered from a message on a Cloud Pub/Sub topic.
    @functions_framework.cloud_event
    def subscribe(cloud_event):
        # 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: %v", 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=nodejs16 \
--region=REGION \
--source=. \
--entry-point=helloPubSub \
--trigger-topic=YOUR_TOPIC_NAME
優先する Node.js のバージョンを指定するには、--runtime フラグに次の値を使用します。
  • nodejs16(推奨)
  • nodejs14
  • nodejs12
  • nodejs10

Python

gcloud functions deploy python-pubsub-function \
--gen2 \
--runtime=python310 \
--region=REGION \
--source=. \
--entry-point=subscribe \
--trigger-topic=YOUR_TOPIC_NAME
優先する Python バージョンを指定するには、--runtime フラグに次の値を使用します。
  • python310(推奨)
  • python39
  • python38
  • python37

Go

gcloud functions deploy go-pubsub-function \
--gen2 \
--runtime=go116 \
--region=REGION \
--source=. \
--entry-point=HelloPubSub \
--trigger-topic=YOUR_TOPIC_NAME
優先する Go バージョンを指定するには、--runtime フラグに次の値を使用します。
  • go116(推奨)
  • go113
  • go111

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 バージョンを指定するには、--runtime フラグに次の値を使用します。
  • java17(推奨)
  • java11

C#

gcloud functions deploy csharp-pubsub-function \
--gen2 \
--runtime=dotnet3 \
--region=REGION \
--source=. \
--entry-point=HelloPubSub.Function \
--trigger-topic=YOUR_TOPIC_NAME
優先する .NET バージョンを指定するには、--runtime フラグに次の値を使用します。
  • dotnet6(プレビュー版)
  • dotnet3(推奨)

Ruby

gcloud functions deploy ruby-pubsub-function \
--gen2 \
--runtime=ruby30 \
--region=REGION \
--source=. \
--entry-point=hello_pubsub \
--trigger-topic=YOUR_TOPIC_NAME
優先する Ruby バージョンを指定するには、--runtime フラグに次の値を使用します。
  • ruby30(推奨)
  • ruby27
  • ruby26

PHP

gcloud functions deploy php-pubsub-function \
--gen2 \
--runtime=php81 \
--region=REGION \
--source=. \
--entry-point=helloworldPubsub \
--trigger-topic=YOUR_TOPIC_NAME
優先する PHP バージョンを指定するには、--runtime フラグに次の値を使用します。
  • php81(推奨)
  • php74

ここで、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. 関数のログで結果を確認します。ここで、FUNCTION_NAME は関数の名前です。

    gcloud beta functions logs read FUNCTION_NAME --gen2

    ログの出力に、新しい「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 を削除することもできます。