オブジェクト変更通知

オブジェクトの変更通知を使用すると、オブジェクトが更新されたりバケットに追加されたりした際にアプリケーションに通知できます。

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

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

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

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

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

通知チャネルが開始されると、バケット内のオブジェクトが追加、更新、削除されるたびに 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.googleapis.com
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 リクエストを開始したアプリケーションの Google Cloud コンソール プロジェクトに関連付けられます。これは、たとえばユーザーが、OAuth2 フローを介してインストール済みのアプリケーションまたはウェブアプリにアクセス権を付与した場合、アプリケーションによって作成された通知チャンネルが、監視対象のバケットが含まれているプロジェクトではなくアプリケーションのプロジェクトに関連付けられることを意味します。

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

通知チャンネルの削除

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

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

POST /storage/v1/channels/stop HTTP/1.1
Host: storage.googleapis.com
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.googleapis.com/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.googleapis.com/storage/v1/b/BucketName/o?alt=json

{
 "kind": "storage#object",
 "id": "BucketName/ObjectName",
 "selfLink": "https://www.googleapis.com/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.googleapis.com/storage/v1/b/BucketName/o/ObjectName?generation=1367014943964000&alt=media",
 "owner": {
  "entity": "user-jane@gmail.com"
 },
 "crc32c": "C7+82w==",
 "etag": "COD2jMGv6bYCEAE="
}
ここで、ResourceState は次のようになります。
  • exists - オブジェクトの追加と更新の場合。
  • not_exists - オブジェクトの削除の場合。

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

信頼できる配信

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

  • 通知の配信の試行に失敗した場合は、追加の試行が実行されます。追加の配信の試行間隔は、exponential backoff アルゴリズムによって決定され、最初の失敗の 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://APPLICATION_ID.appspot.com
      
      自分のドメイン名を使用してアプリケーションをデプロイした場合は、前のコマンドで appspot.com の代わりにそのドメイン名を使用します。
    2. プロジェクトの [ロギング] ページに移動します。必要に応じてログに記録されたメッセージのリストを更新します。アプリケーションが送信したログメッセージがログに記録されていることを確認します。
    3. オブジェクトをバケットに追加します。Cloud Storage がアプリケーションに通知し、アプリケーションがメッセージをログに記録します。
    4. プロジェクトの [ロギング] ページに移動します。ログに記録されたメッセージのリストを更新し、オブジェクトのメッセージを見つけます。
  6. 通知チャンネルを削除する
    バケットを監視する notification コマンドを実行したときに返されたチャンネル ID とリソース ID を指定して、通知チャンネルを削除します。