Notificação de alteração de objeto

A notificação de alteração de objeto pode ser usada para notificar uma aplicação quando um objeto é adicionado, atualizado ou eliminado de um contentor.

Deve usar a notificação de alteração de objeto?

Geralmente, não deve usar a notificação de alteração de objeto. A ferramenta recomendada para gerar notificações que monitorizam as alterações aos objetos nos seus contentores do Cloud Storage são as notificações do Pub/Sub para o Cloud Storage, porque são mais rápidas, flexíveis, fáceis de configurar e rentáveis. Para um guia passo a passo sobre como configurar notificações do Pub/Sub para o Cloud Storage, consulte o artigo Configurar notificações do Pub/Sub para o Cloud Storage.

Se estiver a usar atualmente a notificação de alteração de objeto, recomendamos que migre para as notificações do Pub/Sub. Para obter informações sobre como migrar para as notificações do Pub/Sub, consulte o artigo Migre das notificações de alteração de objetos para as notificações do Pub/Sub.

Como funciona a notificação de alteração de objeto

Uma aplicação cliente pode enviar um pedido para monitorizar alterações aos objetos num determinado contentor.

A conclusão de um pedido de visualização cria um novo canal de notificação. Um canal de notificação é o meio através do qual uma mensagem de notificação é enviada para uma aplicação que está a monitorizar um contentor. Atualmente, apenas é suportado um tipo de canal de notificação, um webhook.

Depois de criar um canal de notificação, o Cloud Storage notifica a aplicação sempre que um objeto é adicionado, atualizado ou removido do contentor. Por exemplo, quando adiciona uma nova imagem a um contentor, uma aplicação pode receber uma notificação para criar uma miniatura.

Detalhes da notificação de alteração de objeto

Terminologia

A tabela seguinte contém uma descrição de vários termos usados ao longo da documentação de notificação de alteração de objetos:

Vigência Descrição
URL da aplicação O URL da sua aplicação. Este é o endereço para o qual as notificações vão ser enviadas. Tenha em atenção que tem de ser um URL HTTPS. Os URLs HTTP não são permitidos.
Identificador do canal O identificador de um canal de notificações. Tem de ser exclusivo num determinado contentor, ou seja, se existirem vários canais de notificação para um único contentor, cada canal de notificação tem de ter um identificador de canal distinto. Este identificador é enviado para a sua aplicação juntamente com cada mensagem de notificação.
Identificador de recursos Um identificador opaco do recurso que está a ser monitorizado. O identificador do recurso é necessário para parar um canal de notificação. Pode obter este identificador a partir da resposta a um pedido de observação ou do cabeçalho X-Goog-Resource-Id de mensagens de eventos de notificação.
Símbolo de cliente (opcional) Os tokens de cliente podem ser usados para validar eventos de notificações. Para tal, defina um token de cliente personalizado com o seu pedido de visualização. As mensagens de notificação contêm este token para que possa verificar a respetiva autenticidade.

Crie um canal de notificação

Para começar a monitorizar um contentor de eventos de notificação de alterações, faz um pedido watchAll. Isto cria um canal de notificação que envia eventos de notificação para o address especificado para o bucket especificado. O canal de notificação inclui um token de cliente personalizado e um identificador do canal, se especificado.

Um exemplo de pedido POST para ver um contentor:

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"
}

Autorização de notificações

Quando monitoriza um contentor, o canal de notificação que está a ser criado é associado ao projeto da consola Google Cloud da aplicação que inicia o pedido da API. Isto significa, por exemplo, que se um utilizador conceder acesso a uma aplicação instalada ou a uma aplicação Web através de um fluxo OAuth2, um canal de notificação criado pela aplicação será associado ao projeto da aplicação e não ao projeto que contém o contentor que está a ser monitorizado.

Uma vez que uma conta de serviço está associada a um projeto, se usar uma conta de serviço para monitorizar um contentor, é criado um canal de notificação no projeto da conta de serviço.

Pare um canal de notificações

A interrupção de um canal de notificação de alteração de objeto impede que as notificações de alteração de objeto sejam publicadas no URL da aplicação associada. Para parar com êxito um canal de notificação de alteração de objeto, tem de conhecer os seguintes parâmetros:

  • O identificador do recurso do canal de notificação de alteração de objeto (RESOURCE_ID)
  • O identificador do canal do canal de notificação de alteração de objeto (CHANNEL_ID)
  • O utilizador ou a conta de serviço que criou o canal de notificação de alteração de objeto. Apenas o criador do canal o pode parar.

Linha de comandos

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

    Activate Cloud Shell

    At the bottom of the Google 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. Instale o gsutil.
  3. Para encontrar todos os canais de notificação de alteração de objetos ativos e listar os respetivos detalhes para identificar o CHANNEL_ID, o RESOURCE_ID e a conta de serviço que criou o canal, use o comando gsutil notification list:
      gsutil notification list -o gs://BUCKET_NAME
      

    Onde:

    BUCKET_NAME é o nome do seu contentor. Por exemplo, my-bucket.

    Se o pedido for bem-sucedido, o comando devolve uma saída semelhante à seguinte mensagem:

    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. Se o canal tiver sido criado por uma conta de serviço, tem de se fazer passar pelo criador dessa conta de serviço para garantir que tem as autorizações necessárias.
    gcloud config set auth/impersonate_service_account CHANNEL_CREATOR

    Onde:

    CHANNEL_CREATOR é a conta de serviço que criou o canal.
  5. Pare o canal de notificação de alteração de objetos do contentor através do CHANNEL_ID e do RESOURCE_ID identificados.
    gsutil notification stopchannel CHANNEL_ID RESOURCE_ID

    Onde:

    • CHANNEL_ID é o identificador do canal de notificações de alterações de objetos.
    • RESOURCE_ID é o identificador do recurso do canal de notificação de alteração de objeto.
  6. APIs REST

    API JSON

    Para parar um canal de notificação, faz um pedido stop. Esta ação interrompe todos os eventos de notificação publicados no identificador de recurso especificado (resourceId) e no par de identificadores de canais (id). Os canais adicionais para o mesmo recurso não são afetados. Os identificadores de recursos e canais podem ser encontrados na resposta de um pedido de monitorização ou no corpo das mensagens de eventos de notificação.

    Um exemplo de um pedido POST para parar um canal:

    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"
    }

Tipos de mensagens de eventos de notificação

Sincronizar

É enviado um evento de notificação quando é criado um novo canal de notificação após a emissão de um pedido de visualização. Após receber o evento de sincronização, todas as alterações posteriores ao contentor são enviadas para o URL da aplicação configurado para o canal.

A notificação é enviada como um pedido POST para o URL da aplicação configurado. Não existe um corpo no pedido. Os metadados de notificação de sincronização estão contidos nos cabeçalhos do pedido. Segue-se um exemplo do pedido de notificação 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

Adição, atualização ou eliminação de objetos

É enviado um evento de notificação quando um novo objeto é adicionado a um contentor, o conteúdo ou os metadados de um objeto existente foram modificados ou um objeto é eliminado de um contentor.

A notificação é enviada como um pedido POST para o URL da aplicação configurado. O corpo do pedido contém uma mensagem codificada em JSON, conforme mostrado no seguinte pedido de notificação:

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-jeffersonloveshiking@gmail.com"
 },
 "crc32c": "C7+82w==",
 "etag": "COD2jMGv6bYCEAE="
}
onde ResourceState é:
  • exists: para adições e atualizações de objetos.
  • not_exists: para eliminações de objetos.

e onde o conteúdo da mensagem JSON contém a representação atual do objeto, conforme descrito em Descrição do recurso do objeto.

Envio fiável

A notificação de alteração de objeto tenta enviar notificações para a sua aplicação de forma fiável. No entanto, tenha em atenção que as notificações podem sofrer atrasos indefinidamente e a pontualidade não é garantida. Uma vez que a sua aplicação pode nem sempre estar disponível, são seguidas as seguintes regras quando são enviadas notificações:

  • Se uma tentativa de entrega de notificação falhar, são feitas tentativas adicionais. O intervalo entre as tentativas de entrega adicionais é determinado por um algoritmo de recuo exponencial que começa com uma repetição 30 segundos após a falha inicial. As entregas subsequentes são tentadas em intervalos cada vez maiores, até um intervalo máximo de 90 minutos. Tenha em atenção que os intervalos de novas tentativas subsequentes são ligeiramente aleatórios para não ocorrerem em valores exponenciais exatos. Após atingir o intervalo máximo de repetição de 90 minutos, as repetições subsequentes continuam a ocorrer a cada 90 minutos durante 7 dias. Se não for possível entregar a notificação nesse período, esta é anulada.
  • Se não for possível aceder à sua aplicação após 20 segundos ou se a sua aplicação responder com um dos seguintes códigos de resposta HTTP, a tentativa de entrega de notificações é tratada como uma falha e é repetida:
    • 500 Erro interno do servidor
    • 502 Gateway incorreto
    • 503 Serviço indisponível
    • 504 Tempo limite do gateway
  • Se a sua aplicação responder com um dos seguintes códigos de resposta HTTP, a notificação é tratada como entregue com êxito:
    • 102 Processing
    • 200 OK
    • 201 Created
    • 202 Accepted
    • 204 No Content
  • Quaisquer outros códigos de resposta HTTP devolvidos pela sua aplicação são tratados como falhas permanentes e não são repetidos.

Exemplo de aplicação cliente

Esta secção explica como criar uma aplicação cliente do App Engine que processa eventos de notificação de alterações.

A aplicação de exemplo contém uma classe denominada MainPage. Quando o utilizador atualiza ou adiciona um objeto ao contentor, a classe MainPage processa o evento de notificação. Para simplificar, o método post que faz o processamento real apenas regista uma mensagem com a hora em que a notificação foi recebida. Pode substituir este código pela sua lógica de processamento real. Se ainda não se sentir confortável a desenvolver aplicações do App Engine, experimente implementar uma app de exemplo ou seguir um tutorial antes de continuar.

  1. Configurar a aplicação
    Crie o ficheiro de configuração app.yaml para especificar a aplicação cliente que processa os eventos de notificação de alteração do contentor.
    application: APPLICATION
    version: 1
    runtime: python38
    api_version: 1
    threadsafe: true
    
    handlers:
    - url: /.*
      script: change_notification_client.app
  2. Criar a aplicação
    O exemplo seguinte implementa uma aplicação cliente para processar eventos de notificação de alterações de um contentor. Atribua-lhe o nome change_notification_client.py e, em seguida, implemente a sua app:
    """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. Atribuir a autorização de acesso da aplicação ao contentor.
    Se o seu contentor for propriedade de uma conta de serviço diferente da sua app do App Engine, conceda ao aplicativo acesso de PROPRIETÁRIO ao contentor.
  4. Comece a monitorizar o contentor para ver alterações de objetos.
    Crie um canal de notificação para a sua aplicação monitorizando o contentor através de um pedido watchAll com o address do URL da sua aplicação do App Engine, por exemplo: https://ApplicationId.appspot.com/.
  5. Testar a aplicação.
    Para ver se a aplicação funciona como esperado, siga estes passos:
    1. Para garantir que a aplicação foi implementada e funciona corretamente, execute o seguinte comando curl:
      curl -X Post https://APPLICATIONID.appspot.com
      Se usou o seu próprio nome de domínio para implementar a aplicação, use-o em vez de appspot.com no comando anterior.
    2. Aceda à página Registo do seu projeto. Atualize a lista das mensagens registadas, se necessário. Verifique se a mensagem de registo emitida pela aplicação é registada.
    3. Adicione um objeto ao contentor. O Cloud Storage notifica a aplicação, que, em seguida, regista uma mensagem.
    4. Aceda à <a href="https://console.cloud.google.com/project//logs">página de registo do seu projeto. Atualize a lista das mensagens registadas e encontre a mensagem para a cópia do objeto.
    5. </ol>
      

    6. Pare o canal de notificação
      Pare o canal de notificação especificando os identificadores do canal e do recurso devolvidos quando emitiu o comando de notificação para criar um canal de notificação.