オブジェクト変更通知


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

この機能は、Cloud Pub/Sub Notifications for Cloud Storage とは別であるので注意してください。Cloud Pub/Sub Notifications は、Cloud Storage バケット内のオブジェクトの変更をトラッキングするのに推奨される方法です。Cloud Pub/Sub Notifications は、より高速で、柔軟性が高く、設定が簡単で、コスト効率が高いからです。

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

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

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

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

下の図は、変更通知を処理するアプリケーションのデータフローの例を示しています。HTTPS POST リクエストを受信することができる任意のアプリケーション サーバーを使用して変更通知を処理できます。

オブジェクトの変更通知のコンポーネント
オブジェクトの変更通知のコンポーネント

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

用語

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

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

バケットの監視

バケットの通知変更イベントの監視を開始するには、次の gsutil notification watchbucket コマンドを使用できます。

gsutil notification watchbucket [-i ChannelId] [-t ClientToken] ApplicationUrl gs://BucketName

これにより、指定されたバケットについての通知イベントを指定されたアプリケーションの URL に送信する通知チャネルが作成されます。指定した場合、通知チャネルにカスタム クライアント トークンとチャネル ID が含まれます。

このコマンドについて詳しくは、gsutil help notification watchbucket コマンドを実行してください。

gsutil によって生成されたバケットを監視するための POST リクエストの例:

POST /storage/v1/b/BucketName/o/watch?alt=json HTTP/1.1
Host: www.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 Platform コンソール プロジェクトに関連付けられます。これは、たとえばユーザーが、OAuth2 フローを介してインストール済みのアプリケーションまたはウェブアプリにアクセス権を付与した場合、アプリケーションによって作成された通知チャネルが、監視対象のバケットが含まれているプロジェクトではなくアプリケーションのプロジェクトに関連付けられることを意味します。

オブジェクト変更通知のシナリオでは、次の 3 つの手順で承認を確認します。

サービス アカウントの作成

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

新しいサービス アカウントを承認するには:

  1. Google Cloud Platform コンソールで認証情報のリストを開きます。

    認証情報のリストを開く

  2. [認証情報を作成] をクリックします。
  3. [サービス アカウント キー] を選択します。

    [サービス アカウント キーの作成] ウィンドウが開きます。

  4. [サービス アカウント] の下にあるプルダウン ボックスをクリックし、[新しいサービス アカウント] をクリックします。
  5. サービス アカウントの名前を入力します。
  6. 必要なアクセスレベルをサービス アカウントに付与する Cloud Storage の役割を選択します。
  7. デフォルトの [サービス アカウント ID] を使用するか、別の ID を作成します。
  8. [キーのタイプ] で [JSON] または [P12] を選択します。
  9. [作成] をクリックします。

    サービス アカウントが作成されたことを示すウィンドウが表示され、選択したキーのタイプの秘密鍵が自動的にダウンロードされます。P12 キーを選択した場合は、秘密鍵のパスワード(「notasecret」)が表示されます。

  10. [閉じる] をクリックします。

サービス アカウントを使用するための gsutil の設定

gsutil を設定してサービス アカウントを使用するには、Google Cloud SDK を使用し、オブジェクト変更通知を含む Google Cloud Platform の操作のための認定されたアカウントとして、サービス アカウントを追加します。認証情報を追加した後は、すべての後続の gsutil コマンドがサービス アカウントの認証情報を使用します。

サービス アカウントに基づいて認証情報を作成するには:

  1. 最新バージョンの Cloud SDK であることを確認します。次のコマンドを実行してコンポーネントを更新できます。
    gcloud components update
    
  2. gcloud auth activate-service-account コマンドを使用し、サービス アカウントのメールアドレスと秘密鍵を指定します。
    gcloud auth activate-service-account service-account-email --key-file path/to/key.p12
    

    各パラメータの内容は次のとおりです。

    • service-account-email はサービス アカウントのメールアドレスです。1234567890123-abcdefghijklmonpqrstuvwxz01234567@developer.gserviceaccount.com のように表示されます。
    • path/to/key.p12 は、サービス アカウントを作成したときにダウンロードするように指示された鍵です。鍵をなくした場合は、Google Cloud Platform コンソールで [認証情報] ページに戻り、新しい鍵を生成することができます。
  3. サービス アカウントがアクティブな認証情報アカウントであることを確認します。
    $ gcloud auth list
    Credentialed accounts:
    - 1234567890123-abcdefghijklmonpqrstuvwxz01234567@developer.gserviceaccount.com (active)
    

    サービス アカウントの認証情報に active が表示されます。これで、実行するすべての gsutil 通知コマンドでサービス アカウントの認証情報が使用されるようになります。

通知を受信するドメインの識別

監視リクエストが成功するのは、通知 URL が通知チャネルのプロジェクトによってドメインのホワイトリストに登録されている場合のみです。

ドメインのホワイトリストに登録するには:

  1. Search Console 検証プロセスを使って、ドメインを所有していることを確認します。
  2. GCP Console で [認証情報] ページの [ドメインの確認] タブに移動します。

    [認証情報] ページに移動

  3. [ドメインを追加] をクリックします。
  4. [Webhook 通知の設定] ダイアログで、ドメインを入力し、確認します。

    Webhook 通知の設定ダイアログ

  5. [ドメインを追加] をクリックします。

    ドメイン確認のトラブルシューティングの方法は次のとおりです。

    • ドメインは、Search Consolehttps:// URL を登録されているか、あるいはドメイン名プロバイダの検証方法で検証されている必要があります。
    • GCP Console プロジェクトのオーナーまたは編集者になっていること(プロジェクト メンバーと権限をご覧ください)および通知を受信するドメインの所有者になっていることを確認します。ドメインのサイトオーナーではない場合は、ドメイン所有者に連絡して、確認済みのオーナーとして追加してもらいます(サイト所有者を追加 / 削除)をご覧ください)。
    • ウェブマスター ツールの Google APIs Explorer を使えば、ドメインのリストを表示し、特にドメインの siteUrl プロパティの先頭が https:// であることを確認できます。

通知チャネルの削除

通知チャネルを停止するには、gsutil notification stopchannel コマンドを使用します。

gsutil notification stopchannel ChannelId ResourceId

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

このコマンドについて詳しくは、gsutil help notification stopchannel コマンドを実行してください。

gsutil によって生成されるチャネルを停止するための POST リクエストの例:

POST /storage/v1/channels/stop HTTP/1.1
Host: www.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://www.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://www.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://www.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: <ApplicationId>
    version: 1
    runtime: python27
    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 アプリケーションと異なるサービス アカウントに所有されている場合は、次のコマンドを実行してバケットにアプリケーション オーナーのアクセス権を付与します。
    gsutil acl ch -u ApplicationId@appspot.gserviceaccount.com:OWNER gs://BucketName
    
  4. バケットのオブジェクト変更の監視を開始します
    gsutil でバケットを監視することによってアプリケーションへの通知チャネルを作成します。
    gsutil notification watchbucket ApplicationUrl gs://BucketName
    
    ApplicationUrl は、App Engine アプリケーションの URL です(例: https://ApplicationId.appspot.com/)。
  5. アプリケーションをテストします
    アプリケーションが予想どおりに動作するかを確認する手順は次のとおりです。
    1. アプリケーションが正しくデプロイされたこと、機能することを確認するには、次の curl コマンドを実行します。
      curl -X Post https://<ApplicationId>.appspot.com
      
      自分のドメイン名を使用してアプリケーションをデプロイした場合は、前のコマンドで appspot.com の代わりにそのドメイン名を使用します。
    2. プロジェクトの [ロギング] ページに移動します。必要に応じてログに記録されたメッセージのリストを更新します。アプリケーションが送信したログメッセージがログに記録されていることを確認します。
    3. オブジェクトをバケットに追加します。次のように gsutil ツールを使用できます。
      gsutil cp ObjectName gs://BucketName/
      
      Cloud Storage がアプリケーションに通知し、アプリケーションがメッセージをログに記録します。
    4. プロジェクトの [ロギング] ページに移動します。ログに記録されたメッセージのリストを更新し、オブジェクトのメッセージを見つけます。
  6. 通知チャネルを削除します。
    バケットを監視する notification コマンドを実行したときに返されたチャネル ID とリソース ID を指定して通知チャネルを削除します。
    gsutil notification stopchannel <channel_id> <resource_identifier>
    

トップへ戻る

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Cloud Storage ドキュメント