Como acionar o processamento de eventos no Cloud Storage usando o Eventarc e o Cloud Functions (2a geração)

1. Visão geral

Neste laboratório, você vai aprender a usar os eventos de bucket do Cloud Storage e o Eventarc para acionar o processamento de eventos. Você vai usar o Cloud Functions (2nd gen) para analisar dados e processar imagens. A função vai usar a API Vision do Google e salvar a imagem resultante no bucket do Cloud Storage.

4756e4c218d84e26.png

O que você vai aprender

Como criar um pipeline de processamento de imagens.

  • Configurar buckets do Storage
  • Criar uma função do Cloud para ler e gravar objetos no Cloud Storage
  • Integrar a API Vision para detectar imagens de alimentos
  • Implantar uma Função do Cloud
  • Implantar um gatilho do Eventarc
  • Testar e validar a solução de ponta a ponta

Pré-requisitos

  • Para fazer este laboratório, é preciso saber usar o console do Cloud e ambientes shell.
  • Ter experiência prévia com Cloud Storage, Cloud Functions ou API Vision é útil, mas não obrigatório.

2. Configuração e requisitos

Configuração do projeto do Google Cloud

  1. Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • O Nome do projeto é o nome de exibição para os participantes do projeto. É uma string de caracteres não usada pelas APIs do Google Você pode atualizar a qualquer momento.
  • O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser mudado após a definição. O console do Cloud gera automaticamente uma string exclusiva. normalmente você não se importa com o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, que normalmente é identificado como PROJECT_ID. Se você não gostar do ID gerado, poderá gerar outro ID aleatório. Como alternativa, você pode tentar o seu próprio e ver se ele está disponível. Ela não pode ser alterada após essa etapa e permanecerá durante a duração do projeto.
  • Para sua informação, há um terceiro valor, um Número de projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
  1. Em seguida, ative o faturamento no console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não será muito cara, se tiver algum custo. Para encerrar os recursos e não gerar faturamento além deste tutorial, exclua os recursos criados ou exclua o projeto inteiro. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.

Ativar o Cloud Shell

Ative o Cloud Shell clicando no ícone à direita da barra de pesquisa.

8613854df02635a3.png

Configuração do ambiente

  1. Execute os comandos abaixo no terminal do Cloud Shell para criar um projeto e as variáveis de ambiente relacionadas a recursos.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NAME=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
export REGION=us-east1 
export UPLOAD_BUCKET=gs://menu-item-uploads-$PROJECT_ID
export BUCKET_THUMBNAILS=gs://menu-item-thumbnails-$PROJECT_ID
export MENU_SERVICE_NAME=menu-service
export USER_EMAIL=$(gcloud config list account --format "value(core.account)")
  1. Ative as APIs necessárias para o laboratório
gcloud services enable \
    vision.googleapis.com \
    cloudfunctions.googleapis.com \
    pubsub.googleapis.com \
    cloudbuild.googleapis.com \
    logging.googleapis.com \
    eventarc.googleapis.com \
    artifactregistry.googleapis.com \
    run.googleapis.com \
    --quiet
  1. Ative as APIs necessárias para o laboratório. (Etapa específica do Qwiklabs)
gcloud services disable cloudfunctions.googleapis.com
gcloud services enable cloudfunctions.googleapis.com
  1. Clonar o repositório
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git && cd cymbal-eats/cloud-functions

3. Configurar buckets do Cloud Storage

Criar buckets do Storage

Criar buckets do Cloud Storage para upload e miniaturas para o pipeline de processamento de imagens.

Use o comando gsutil mb e um nome exclusivo para criar dois buckets:

  1. Fazer upload do bucket em que as imagens serão enviadas primeiro
  2. Bucket de miniaturas para armazenar imagens de miniatura geradas

Crie um bucket para fazer upload de novas imagens:

gsutil mb -p $PROJECT_ID -l $REGION $UPLOAD_BUCKET

Exemplo de saída:

Creating gs://menu-item-uploads-cymbal-eats-8399-3119/...

Crie um bucket para armazenar as miniaturas geradas:

gsutil mb -p $PROJECT_ID -l $REGION $BUCKET_THUMBNAILS

Exemplo de saída:

Creating gs://menu-item-thumbnails-cymbal-eats-8399-3119/...

Atualizar permissões de bucket

Atualize as permissões do bucket de armazenamento para conceder permissões de leitura aos usuários.

Use o comando gsutil iam ch para conceder permissão de leitura e gravação de objetos no seu bucket:

gsutil iam ch allUsers:objectViewer $UPLOAD_BUCKET
gsutil iam ch allUsers:objectViewer $BUCKET_THUMBNAILS

Exemplo de saída

Updated IAM policy for project [cymbal-eats-8399-3119].
[...]

4. Configurar contas de serviço

Crie uma conta de serviço personalizada para a função do Cloud processar miniaturas:

export CF_SERVICE_ACCOUNT=thumbnail-service-sa
gcloud iam service-accounts create ${CF_SERVICE_ACCOUNT}

Conceda o papel artifactregistry.reader para permitir operações de leitura do Artifact Registry:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role "roles/artifactregistry.reader"

Conceda o papel storage.objectCreator para permitir o armazenamento de imagens geradas no bucket de miniaturas:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role "roles/storage.objectCreator"

Conceda o papel run.invoker para permitir a invocação do serviço do Cloud Run:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role "roles/run.invoker"

Conceda o papel eventarc.eventReceiver para permitir o recebimento de eventos de provedores:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role "roles/eventarc.eventReceiver"

Conceda o papel pubsub.publisher à conta de serviço do Cloud Storage. Assim, a conta de serviço poderá publicar eventos quando as imagens forem enviadas para o bucket.

GCS_SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER)

gcloud projects add-iam-policy-binding $PROJECT_NUMBER \
    --member "serviceAccount:$GCS_SERVICE_ACCOUNT" \
    --role "roles/pubsub.publisher"

5. Visão geral da função de processamento de imagens

Crie uma função para fazer o download de uma imagem do Cloud Storage, redimensionar a imagem e fazer upload dela de volta para o Cloud Storage. A função vai chamar a API Vision para atribuir um rótulo de descrição à imagem. A função vai verificar o rótulo da descrição. Se o rótulo identificar a imagem como "Comida" um evento será enviado ao serviço de menu para atualizar a imagem e a miniatura do item de menu.

4c3c3b758dba6a9f.png

Como acionar uma função

As funções do Cloud Storage são baseadas em notificações do Pub/Sub do Cloud Storage e oferecem suporte a tipos de eventos semelhantes:

Neste laboratório, você vai implantar e acionar uma função quando um objeto for finalizado no Cloud Storage.

Finalização do objeto

Os eventos de finalização de objeto são acionados quando uma operação de "gravação" de um objeto do Cloud Storage é finalizada. Particularmente, isso significa que a criação de um novo objeto ou a substituição de um objeto existente aciona esse evento. Operações de atualização de metadados e arquivamento são ignoradas por esse acionador.

6. Integrar o Cloud Storage

Ele também serve para o armazenamento de objetos no Google Cloud. Um objeto é um dado imutável composto de um arquivo em qualquer formato. Os objetos são armazenados em contêineres chamados de buckets. Todos os buckets estão associados a um projeto, e é possível agrupar os projetos em uma organização. As bibliotecas de cliente e APIs possibilitam a integração com o Cloud Storage

Neste laboratório, você vai usar a biblioteca de cliente para ler e gravar objetos no Cloud Storage.

Instalar a biblioteca de cliente

As bibliotecas de cliente do Cloud estão disponíveis em várias linguagens de programação conhecidas. Para começar a usar as bibliotecas, você precisa instalar a biblioteca de cliente.

Usar a biblioteca de cliente

Os detalhes de implementação dependem da linguagem de programação. Para usar a biblioteca de cliente no seu aplicativo, a primeira etapa é importar as dependências do Cloud Storage. Por exemplo, no projeto Node.js, as importações são adicionadas no arquivo package.json. O snippet abaixo mostra o aviso do arquivo package.json deste laboratório.

package.json

{
    "name": "thumbnail-service",
    "version": "0.1.0",
    "dependencies": {
      "@google-cloud/functions-framework": "^3.0.0",
      "@google-cloud/storage": "^5.18.2",
      "@google-cloud/vision": "^2.4.2",
        ...
    }
  }

Registrar um callback do CloudEvent

Registre um callback do CloudEvent com o Functions Framework que será acionado pelo Cloud Storage quando uma nova imagem for carregada no bucket.

index.js

functions.cloudEvent('process-thumbnails', async (cloudEvent) => {
    console.log(`Event ID: ${cloudEvent.id}`);
    console.log(`Event Type: ${cloudEvent.type}`);
    ...

Como criar um objeto de referência de armazenamento

Depois que as bibliotecas de cliente forem importadas, será necessário criar um novo cliente de armazenamento e buckets com os quais seu aplicativo interagirá.

index.js

const storage = new Storage();
const bucket = storage.bucket(file.bucket);
const thumbBucket = storage.bucket(process.env.BUCKET_THUMBNAILS);

Fazer o download de objetos do Cloud Storage

index.js

await bucket.file(file.name).download({
            destination: originalFile
        });

fazer upload de objetos no Cloud Storage;

Você pode enviar solicitações de upload ao Cloud Storage de três maneiras: de solicitação única, retomável ou upload de várias partes da API XML. Para uploads maiores ou por streaming, use os uploads retomáveis. Com a API XML, os arquivos são enviados em partes e montados como um único objeto. Para objetos menores, use uploads de solicitação única.

O código abaixo faz upload de uma imagem para o armazenamento em nuvem usando um upload de solicitação única.

index.js

const thumbnailImage = await thumbBucket.upload(thumbFile);

7. Integrar a API Vision

O Cloud Vision permite que os desenvolvedores integrem facilmente recursos de detecção de visão nos aplicativos, incluindo rotulagem de imagens, detecção facial e de pontos de referência, reconhecimento óptico de caracteres (OCR) e marcação de conteúdo explícito.

Instalar a biblioteca de cliente

As bibliotecas de cliente do Cloud estão disponíveis em várias linguagens de programação conhecidas. Para começar a usar as bibliotecas, você precisa instalar a biblioteca de cliente.

Criar um cliente de anotações de imagem

Para acessar as APIs do Google usando os SDKs de cliente oficiais, crie um objeto de serviço com base no documento de descoberta da API, que descreve a API para o SDK. Você precisará buscá-lo no serviço de descoberta da API Vision usando suas credenciais.

index.js

const client = new vision.ImageAnnotatorClient();

Criar uma solicitação da API Vision

A API Vision pode realizar a detecção de recursos em um arquivo de imagem enviando o conteúdo do arquivo como uma string codificada em base64 no corpo da solicitação.

Para criar uma solicitação usando o recurso de imagens para anotar sua imagem. Uma solicitação para essa API tem a forma de um objeto com uma lista de solicitações. Cada item nela contém duas informações:

  • Os dados de imagem codificados em Base64.
  • Uma lista de recursos que você quer anotar na imagem.

index.js

        const client = new vision.ImageAnnotatorClient();
        const visionRequest = {
            image: { source: { imageUri: `gs://${file.bucket}/${file.name}` } },
            features: [
                { type: 'LABEL_DETECTION' },
            ]
        };
        const visionPromise = client.annotateImage(visionRequest);

8. Implantar a função do Cloud

Esse serviço de redimensionamento de imagem faz parte do sistema mais amplo da Cymbal Eats. Nesta seção, você vai implantar apenas os componentes relacionados ao recurso de processamento de imagens. A instalação completa incorpora uma interface para fazer upload da imagem e uma solicitação downstream para armazenar os metadados resultantes. Esses recursos não são instalados como parte deste laboratório.

Os seguintes componentes serão criados durante a implantação da função:

  • Função do Cloud
  • Serviço do Cloud Run
  • Gatilho do Eventarc
  • Tópico e assinatura do Pub/Sub

No terminal cloudshell, execute o comando abaixo para implantar a Função do Cloud com um bucket de gatilho no menu-item-uploads-$PROJECT_ID:

gcloud functions deploy process-thumbnails \
  --gen2 \
  --runtime=nodejs16 \
  --source=thumbnail \
  --region=$REGION \
  --project=$PROJECT_ID \
  --entry-point=process-thumbnails \
  --trigger-bucket=$UPLOAD_BUCKET \
  --service-account="${CF_SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --set-env-vars=BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS,MENU_SERVICE_URL=$MENU_SERVICE_URL \
  --max-instances=1 \
  --quiet

Se a implantação falhar devido a um problema de permissão no bucket de armazenamento de upload, aguarde a propagação das alterações do IAM da etapa anterior. Isso geralmente leva de 1 a 2 minutos e, em seguida, tente implantar novamente.

Exemplo de saída

Deploying function (may take a while - up to 2 minutes)...done.
[...] 

No console do Cloud, revise a Função do Cloud criada:

8148dd29e6757603.png

No console do Cloud, revise o serviço Cloud Run que foi criado para a função:

42e970cdd48cae76.png

No console do Cloud, consulte o gatilho do Eventarc que foi criado para a função:

9441995a5cc62e38.png

No console do Cloud, revise o Tópico e a Assinatura do Pub/Sub que foram criados para o gatilho do Eventarc:

affe089c39ae1465.png

a4c41ede2af300db.png

9. Testar e validar a solução de ponta a ponta

Fazer upload de uma nova foto no Cloud Storage e monitorar o progresso do pipeline à medida que as imagens são analisadas. Você vai monitorar os registros do Cloud Functions para testar a solução de ponta a ponta.

Fazer upload de uma imagem apropriada

2fdd13b63d6148f4.jpeg

  1. Salve esta imagem na máquina local.
  2. Renomeie o arquivo como 1.jpg.
  3. Abra o console do Cloud Storage.
  4. Clique no bucket menu-item-uploads-...
  5. Clique em FAZER UPLOAD DE ARQUIVOS.
  6. Faça upload do arquivo 1.jpg no bucket de armazenamento.
  7. No console do Cloud, acesse Cloud Functions.
  8. Clique em process-thumbails
  9. Clique na guia REGISTROS.

7ab4e783e474c90d.png

  1. Navegue até o bucket menu-item-thumbnails-$PROJECT_ID do Cloud Storage
  2. Verifique se a imagem em miniatura foi criada no bucket de miniaturas

84d8023782eb3e0c.png

Como fazer upload de uma imagem que não é de comida

Para verificar se a função funciona corretamente, faça upload de uma imagem que não contenha um objeto classificado como "Comida" do item de linha.

3226a24251084b28.jpeg

  1. Salve esta imagem na máquina local.
  2. Renomeie o arquivo como 2.jpg.
  3. Abra o console do Cloud Storage.
  4. Clique no bucket menu-item-uploads-...
  5. Clique em FAZER UPLOAD DE ARQUIVOS.
  6. Faça upload do arquivo 2.jpg no bucket de armazenamento.
  7. No console do Cloud, acesse Cloud Functions.
  8. Clique em process-thumbails
  9. Clique na guia REGISTROS.

421c36c342fceea8.png

10. Parabéns!

Parabéns, você concluiu o laboratório.

O que vem em seguida:

Conheça outros codelabs da Cymbal Eats:

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto ou mantenha o projeto e exclua cada um dos recursos.

Excluir o projeto

O jeito mais fácil de evitar cobranças é excluindo o projeto que você criou para este tutorial.