Cloud Functionsの第二世代をPub/Subトリガーで実行する

2023.07.16

Google Cloudのデータエンジニアをしています、はんざわです。
昨日、Cloud Functionsの第二世代をPub/Subトリガーで動かしたいケースがあり、その時の設定方法やメッセージのデータ構造が第一世代と大きく変わっていたので確認した事項をこの記事にまとめたいと思います。

前準備

Pub/Subのトピック作成

トピックの作成は第一世代と同じです。

gcloud pubsub topics create gen2-test

実行するコードの準備

第一世代では、eventcontextでメッセージを受け取っていたのに対し、第二世代ではfunctions_frameworkcloud_eventからメッセージを受け取るように変更されました。
また、引数のcloud_eventCloudEvent型でデータを受け取るため、データを扱うのに必要なライブラリを事前にインストールします。

import base64

+ from cloudevents.http import CloudEvent
+ import functions_framework

+ @functions_framework.cloud_event
- def main(event, context):
+ def main(cloud_event: CloudEvent) -> None:
     for k in cloud_event.data.keys():
         print(f'key: {k}, value: {cloud_event.data[k]}')

     for k in cloud_event.data["message"].keys():
         print(f'key: {k}, value: {cloud_event.data["message"][k]}')

     # Pub/Subのメッセージ取得
     print(base64.b64decode(cloud_event.data["message"]["data"]).decode())

必要なライブラリの準備

functions-framework==3.3.0

必要な権限の付与

第二世代ではCloud Functionsを実行するサービスアカウントにroles/run.invoker(Cloud Run起動元)の権限を割り振る必要があります。
第二世代では裏でCloud Runが動いているため、その影響かと思われます。

Cloud Functionsのデプロイ

gcloud functions deploy gen2-pubsub \
    --gen2 \
    --runtime=python310 \
    --region=asia-northeast1 \
    --entry-point=main \
    --trigger-topic=gen2-test

メッセージの送信

今回の検証ではコマンドで直接メッセージを送っています。もちろんCloud Scheduler等からメッセージを送信することも可能です。

gcloud pubsub topics publish gen2-test --message="Hello World"

出力の確認

関数が受け取ったcloud_eventは以下のような構造になっています。

{
  'data':{
        'message': {
            'data': 'SGVsbG8gV29ybGQ=',
            'messageId': '8002550354770230',
            'message_id': '8002550354770230',
            'publishTime': '2023-07-22T05:38:34.216Z',
            'publish_time': '2023-07-22T05:38:34.216Z'
         },
        'subscription': 'projects/hanzawa-yuya/subscriptions/eventarc-asia-northeast1-gen2-pubsub-537081-sub-336'
  },
  'datacontenttype': 'application/json',
  'id': '7985228906631348',
  'source': '//pubsub.googleapis.com/projects/hanzawa-yuya/topics/gen2-test',
  'specversion': '1.0',
  'type': 'google.cloud.pubsub.topic.v1.messagePublished',
  'time': '2023-07-16T12:35:26.348Z',
}

第一世代と共通ですが、Pub/Subのメッセージデータはbase64でエンコードされた文字列になっていますので、今回のようにデコード処理が必要となります。

$ print(base64.b64decode(cloud_event.data["message"]["data"]).decode())

> Hello World

注意点

Pub/Subトリガーを含むイベントトリガーの場合、第一世代同様にタイムアウトは9分のままです。

タイムアウト時間を増やしたいようであれば以下のような構成も検討してみるといいかもしれません。

  • 参考記事

まとめ

今回の検証でCloud Functionsの第二世代をPub/Subトリガーで動かしてみました。
今後、新しいCloud Functionsを構築する場合は基本的に第二世代で構築することになりそうなので使い慣れていきたいなと思っています。

可能な限り、新しい関数には Cloud Functions(第 2 世代)を選択することをおすすめします。しかしながら、今後も Cloud Functions(第 1 世代)のサポートを継続する予定です。