オブジェクト変更通知

オブジェクト変更通知を使用すると、オブジェクトが更新されたときや、バケットに追加またはバケットから削除されたとき、アプリケーションに通知できます。

オブジェクト変更通知を使用する必要がある場合

通常、オブジェクト変更通知は使用しないでください。Cloud Storage バケット内のオブジェクトに対する変更を追跡する通知を生成するためのおすすめのツールは、Pub/Sub Notifications for Cloud Storage です。Pub/Sub Notifications for Cloud Storage の詳しい設定方法については、Pub/Sub Notifications for Cloud Storage の構成をご覧ください。

現在オブジェクト変更通知を使用している場合は、Pub/Sub 通知への移行をおすすめします。Pub/Sub 通知に移行する方法については、オブジェクト変更通知から Pub/Sub 通知に移行するをご覧ください。

オブジェクト変更通知の仕組み

クライアント アプリケーションは特定のバケット内のオブジェクトの変更を監視するためのリクエストを送信できます。

監視リクエストを実行すると、新しい通知チャネルが作成されます。通知チャネルは、通知メッセージをバケットを監視しているアプリケーションに送信する手段です。現在サポートされている通知チャンネルのタイプは、ウェブフックのみです。

通知チャンネルが作成されると、バケット内のオブジェクトが追加、更新、削除されるたびに Cloud Storage よりアプリケーションに通知されます。たとえば新しい画像がバケットに追加されると、アプリケーションに通知され、サムネイルが作成されます。

オブジェクト変更通知の詳細

用語

次の表では、オブジェクトの変更通知のドキュメントで使用される用語の説明を示しています。

用語 説明
アプリケーション URL アプリケーションの URL。通知が送信されるアドレスです。HTTPS URL を使用する必要があり、HTTP URL は許可されていません。
チャンネル ID 通知チャンネルの ID。特定のバケット内で一意である必要があります。つまり、単一バケットの複数の通知チャネルが存在する場合、それぞれの通知チャネルが異なるチャネル ID を持っている必要があります。この ID は、各通知メッセージとともにアプリケーションに送信されます。
リソース ID 監視されているリソースの不透明な ID。通知チャネルを停止するには、リソース ID が必要です。この ID は、監視リクエストに対するレスポンスか、通知イベント メッセージの X-Goog-Resource-Id ヘッダーから取得できます。
クライアント トークン (省略可)クライアント トークンを使用して、通知イベントを検証できます。この検証を行うには、監視リクエストでカスタム クライアント トークンを設定します。通知メッセージにこのトークンが含まれているので、メッセージが正当であることを確認できます。

通知チャンネルを作成する

バケットで変更通知イベントの監視を開始するには、watchAll リクエストを行います。これにより、指定されたバケットの指定された address に通知イベントを送信する通知チャンネルが作成されます。指定された場合、通知チャンネルにはカスタム クライアント トークンとチャンネル ID が含まれます。

バケットを監視するための POST リクエストの例:

POST /storage/v1/b/BucketName/o/watch?alt=json HTTP/1.1
Host: storage.s3nsapis.fr
Content-Length: 200
User-Agent: google-api-python-client/1.0
Content-Type: application/json
Authorization: Bearer oauth2_token

{
  "token": "ClientToken",
  "type": "web_hook",
  "id": "ChannelId",
  "address": "ApplicationUrl"
}

通知の承認

バケットを監視している場合、作成される通知チャンネルは、API リクエストを送信したアプリケーションの Trusted Cloud コンソール プロジェクトに関連付けられます。これは、たとえばユーザーが、OAuth2 フローを介してインストール済みのアプリケーションまたはウェブアプリにアクセス権を付与した場合、そのアプリケーションによって作成された通知チャンネルは、監視対象のバケットを含むプロジェクトではなく、アプリケーションのプロジェクトと関連付けられることを意味します。

サービス アカウントはプロジェクトに関連付けられているため、サービス アカウントを使用してバケットを監視すると、サービス アカウントのプロジェクト内に通知チャンネルが作成されます。

通知チャンネルを停止する

オブジェクト変更通知チャンネルを停止すると、関連付けられたアプリケーション URL にオブジェクト変更通知が公開されなくなります。オブジェクト変更通知チャンネルを正常に停止するには、次のパラメータを把握しておく必要があります。

  • オブジェクト変更通知チャンネルのリソース ID(RESOURCE_ID
  • オブジェクト変更通知チャンネルのチャンネル ID(CHANNEL_ID
  • オブジェクト変更通知チャンネルを作成したユーザーまたはサービス アカウント。チャンネルを停止できるのは、チャンネルの作成者のみです。

コマンドライン

  1. In the Trusted Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Trusted Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. gsutil をインストールする
  3. アクティブなオブジェクト変更通知チャンネルをすべて検索し、その詳細を一覧表示して、CHANNEL_IDRESOURCE_ID、チャンネルを作成したサービス アカウントを特定するには、gsutil notification list コマンドを使用します。
      gsutil notification list -o gs://BUCKET_NAME
      

    ここで

    BUCKET_NAME はバケットの名前です。たとえば、my-bucket です。

    リクエストが成功すると、コマンドから次のメッセージのような出力が返されます。

    Notification channel 1:
                 Channel identifier: test_channel
                 Resource identifier: htopjgdthsgdt
                 Application URL: url=https://examplepetstore.com/notifications
                 Created by: examplepetstore@xyz.com
                 Creation time: 2020-01-01 00:00:00.764000
  4. チャンネルがサービス アカウントによって作成された場合は、必要な権限があることを確認するために、そのサービス アカウント作成者の権限を借用する必要があります。
    gcloud config set auth/impersonate_service_account CHANNEL_CREATOR

    ここで

    CHANNEL_CREATOR は、チャンネルを作成したサービス アカウントです。
  5. 特定した CHANNEL_IDRESOURCE_ID を使用して、バケットからオブジェクト変更通知チャンネルを停止します。
    gsutil notification stopchannel CHANNEL_ID RESOURCE_ID

    ここで

    • CHANNEL_ID は、オブジェクト変更通知チャンネルのチャンネル ID です。
    • RESOURCE_ID は、オブジェクト変更通知チャンネルのリソース ID です。
  6. REST API

    JSON API

    通知チャンネルを停止するには、stop リクエストを行います。これにより、指定されたリソース ID(resourceId)とチャンネル ID(id)のペアに公開されるすべての通知イベントが停止します。同じリソースのその他のチャンネルは影響を受けません。リソース ID とチャンネル ID は、監視リクエストのレスポンスまたは通知イベント メッセージの本文に含まれています。

    チャンネルを停止する POST リクエストの例:

    POST /storage/v1/channels/stop HTTP/1.1
    Host: storage.s3nsapis.fr
    Content-Length: 200
    User-Agent: google-api-python-client/1.0
    Content-Type: application/json
    Authorization: Bearer oauth2_token
    
    {
      "resourceId": "ResourceId",
      "id": "ChannelId"
    }

通知イベント メッセージ タイプ

同期

監視リクエストの発行後は、新しい通知チャネルが作成される際に通知イベントが送信されます。同期イベントの受信後は、その後のすべてのバケットの変更がチャネルに構成されているアプリケーション URL に送信されます。

通知は、POST リクエストとして構成済みのアプリケーション URL に送信されます。リクエストには本文がありません。リクエストのヘッダーには同期通知メタデータが含まれています。次に sync 通知リクエストの例を示します。

POST /ApplicationUrlPath
Accept: */*
Content-Type: application/json; charset="utf-8"
Content_Length: 0
Host: ApplicationUrlHost
X-Goog-Channel-Id: ChannelId
X-Goog-Channel-Token: ClientToken
X-Goog-Resource-Id: ResourceId
X-Goog-Resource-State: sync
X-Goog-Resource-Uri: https://storage.s3nsapis.fr/storage/v1/b/BucketName/o?alt=json

オブジェクトの追加、更新、削除

新しいオブジェクトがバケットに追加されたとき、既存のオブジェクトのコンテンツまたはメタデータが変更されたとき、またはオブジェクトがバケットから削除されたときに、通知イベントが送信されます。

通知は、POST リクエストとして構成済みのアプリケーション URL に送信されます。次の通知リクエストに示すように、リクエストの本文には、JSON エンコードされたメッセージが含まれています。

POST /ApplicationUrlPath
Accept: */*
Content-Length: 1097
Content-Type: application/json; charset="utf-8"
Host: ApplicationUrlHost
X-Goog-Channel-Id: ChannelId
X-Goog-Channel-Token: ClientToken
X-Goog-Resource-Id: ResourceId
X-Goog-Resource-State: ResourceState
X-Goog-Resource-Uri: https://storage.s3nsapis.fr/storage/v1/b/BucketName/o?alt=json

{
 "kind": "storage#object",
 "id": "BucketName/ObjectName",
 "selfLink": "https://www.s3nsapis.fr/storage/v1/b/BucketName/o/ObjectName",
 "name": "ObjectName",
 "bucket": "BucketName",
 "generation": "1367014943964000",
 "metageneration": "1",
 "contentType": "application/octet-stream",
 "updated": "2013-04-26T22:22:23.832Z",
 "size": "10",
 "md5Hash": "xHZY0QLVuYng2gnOQD90Yw==",
 "mediaLink": "https://content-storage.s3nsapis.fr/storage/v1/b/BucketName/o/ObjectName?generation=1367014943964000&alt=media",
 "owner": {
  "entity": "user-example-service-account@example-project.s3ns-system.iam.gserviceaccount.com"
 },
 "crc32c": "C7+82w==",
 "etag": "COD2jMGv6bYCEAE="
}
ここで、ResourceState は次のようになります。
  • exists - オブジェクトの追加と更新の場合。
  • not_exists - オブジェクトの削除の場合。

JSON メッセージには、オブジェクト リソースの説明に記載されているように、オブジェクトの現在の表現が含まれています。

信頼性の高い配信

オブジェクト変更通知は、信頼できる方法によりアプリケーションへの通知の配信を試行します。ただし通知は無期限に遅延する可能性があり、適時性は保証されないのでご注意ください。アプリケーションが常に使用できるとは限らないため、通知を配信するときには次のルールに従います。

  • 通知の配信の試行に失敗した場合は、追加の試行が実行されます。追加の配信の試行間隔は、指数バックオフ アルゴリズムによって決定され、最初の失敗の 30 秒後から再試行が始まります。後続の配信の試行は間隔が長くなりますが、最大間隔は 90 分です。後続の再試行の間隔は、正確な指数値で発生しないように少々ランダム化されます。最大間隔である 90 分に到達した後は、後続の再試行が 90 分ごとに 7 日間に渡って続行されます。その時間内に通知を配信できない場合、その通知は削除されます。
  • 20 秒経過してもアプリケーションに接続できない場合、または以下のいずれかのレスポンス コードで応答した場合、通知配信の試行は失敗として扱われ、再試行されます。
    • 500 Internal Server Error(内部サーバーエラー)
    • 502 Bad Gateway(不正なゲートウェイ)
    • 503 Service Unavailable(サービス利用不可)
    • 504 Gateway Timeout(ゲートウェイ タイムアウト)
  • アプリケーションが以下のいずれかの HTTP レスポンス コードで応答した場合、通知が正常に配信されたものとして扱われます。
    • 102 Processing(処理中)
    • 200 OK
    • 201 Created(作成済み)
    • 202 Accepted(承諾済み)
    • 204 No Content(コンテンツなし)
  • アプリケーションが他の HTTP レスポンス コードを返した場合、永続的な失敗として扱われ、再試行は実行されません。

クライアント アプリケーションの例

このセクションでは、変更通知イベントを処理する App Engine クライアント アプリケーションの作成方法について説明します。

サンプル アプリケーションには MainPage というクラスが含まれています。ユーザーがバケットのオブジェクトを更新または追加すると、MainPage クラスがその通知イベントを処理します。簡単にするために、実際の処理をする post メソッドでは、メッセージと通知を受けた時刻をログに記録します。このコードを、実際の処理ロジックに置き換えることができます。App Engine アプリケーションの開発に慣れていない場合は、続行する前にサンプルアプリをデプロイするか、チュートリアルを利用してみてください。

  1. アプリケーションの構成
    構成ファイル app.yaml を作成し、バケットの変更通知イベントを処理するクライアント アプリケーションを指定します。
    application: APPLICATION
    version: 1
    runtime: python38
    api_version: 1
    threadsafe: true
    
    handlers:
    - url: /.*
      script: change_notification_client.app
  2. アプリケーションの作成
    バケットの変更通知イベントを処理するクライアント アプリケーションの実装例を次に示します。change_notification_client.py と名前を付けた後、アプリケーションをデプロイします。
    """Notification handling for Google Cloud Storage."""
    
    import json
    import logging
    
    import webapp2
    
    
    class MainPage(webapp2.RequestHandler):
      """Process notification events."""
      def get(self):
        logging.info("Get request to notification page.")
        self.response.write("Welcome to the notification app.")
    
      def post(self):  # pylint: disable-msg=C6409
        """Process the notification event.
    
        This method is invoked when the notification channel is first created with
        a sync event, and then subsequently every time an object is added to the
        bucket, updated (both content and metadata) or removed. It records the
        notification message in the log.
        """
    
        logging.debug(
            '%s\n\n%s',
            '\n'.join(['%s: %s' % x for x in self.request.headers.iteritems()]),
            self.request.body)
    
        # The following code is for demonstration. Replace
        # it with your own notification processing code.
    
        if 'X-Goog-Resource-State' in self.request.headers:
          resource_state = self.request.headers['X-Goog-Resource-State']
          if resource_state == 'sync':
            logging.info('Sync message received.')
          else:
            an_object = json.loads(self.request.body)
            bucket = an_object['bucket']
            object_name = an_object['name']
            logging.info('%s/%s %s', bucket, object_name, resource_state)
        else:
          logging.info("Other post.")
    
    logging.getLogger().setLevel(logging.DEBUG)
    app = webapp2.WSGIApplication([('/', MainPage)], debug=True)

  3. アプリケーションにバケットへのアクセス許可を割り当てます。
    バケットが App Engine アプリと異なるサービス アカウントによって所有されている場合は、アプリケーションのオーナーにバケットへのアクセス権を付与します。
  4. バケットのオブジェクト変更の監視を開始します
    App Engine アプリケーションの URL の address を含む watchAll リクエストを使用してバケットを監視し、アプリケーションへの通知チャンネルを作成します。例:https://ApplicationId.appspot.com/
  5. アプリケーションのテスト
    アプリケーションが予想どおりに動作するかを確認する手順は次のとおりです。
    1. アプリケーションが正しく導入され、機能することを確認するには、次の curl コマンドを実行します:
      curl -X Post https://APPLICATIONID.appspot.com
      自分のドメイン名を使用してアプリケーションをデプロイした場合は、前のコマンドで appspot.com ではなくそのドメイン名を使用します。
    2. プロジェクトの [ロギング] ページに移動します。必要に応じてログに記録されたメッセージのリストを更新します。アプリケーションが送信したログメッセージがログに記録されていることを確認します。
    3. オブジェクトをバケットに追加します。Cloud Storage がアプリケーションに通知し、アプリケーションがメッセージをログに記録します。
    4. プロジェクトの [<a href="https://console.cloud.s3nscloud.fr/project//logs">ロギング] ページに移動します。ログに記録されたメッセージのリストを更新し、オブジェクトのメッセージを見つけます。
    5. </ol>
      

    6. 通知チャンネルを停止する
      通知チャンネルを作成する notification コマンドを実行したときに返されたチャンネル ID とリソース ID を指定して、通知チャンネルを停止します。