Usar fluxos de trabalho para associar serviços


Este tutorial mostra como usar fluxos de trabalho para associar uma série de serviços. Ao ligar dois serviços HTTP públicos através de funções do Cloud Run, uma API REST externa e um serviço do Cloud Run privado, pode criar uma aplicação flexível e sem servidor.

Objetivos

Neste tutorial, vai usar a CLI Google Cloud para criar um único fluxo de trabalho, associando um serviço de cada vez:

  1. Implemente duas funções do Cloud Run: a primeira função gera um número aleatório e, em seguida, transmite esse número à segunda função que o multiplica.
  2. Usando fluxos de trabalho, ligue as duas funções HTTP. Executar o fluxo de trabalho e devolver um resultado que é, em seguida, transmitido a uma API externa.
  3. Usando fluxos de trabalho, ligue uma API HTTP externa que devolva o log para um determinado número. Executar o fluxo de trabalho e devolver um resultado que é, em seguida, transmitido a um serviço do Cloud Run.
  4. Implemente um serviço do Cloud Run que permita apenas o acesso autenticado. O serviço devolve o math.floor para um determinado número.
  5. Usando os fluxos de trabalho, ligue o serviço Cloud Run, execute todo o fluxo de trabalho e devolva um resultado final.

O diagrama seguinte mostra uma vista geral do processo, bem como uma visualização do fluxo de trabalho final:

Visualização de fluxos de trabalho

Custos

Neste documento, usa os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custos com base na sua utilização projetada, use a calculadora de preços.

Os novos Google Cloud utilizadores podem ser elegíveis para uma avaliação gratuita.

Antes de começar

As restrições de segurança definidas pela sua organização podem impedir a conclusão dos seguintes passos. Para informações de resolução de problemas, consulte o artigo Desenvolva aplicações num ambiente Google Cloud restrito.

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. Se estiver a usar um fornecedor de identidade (IdP) externo, primeiro, tem de iniciar sessão na CLI gcloud com a sua identidade federada.

  4. Para inicializar a CLI gcloud, execute o seguinte comando:

    gcloud init
  5. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Artifact Registry, Cloud Build, Cloud Run, Cloud Run functions, Cloud Storage, and Workflows APIs:

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com run.googleapis.com cloudfunctions.googleapis.com storage.googleapis.com workflows.googleapis.com
  8. Install the Google Cloud CLI.

  9. Se estiver a usar um fornecedor de identidade (IdP) externo, primeiro, tem de iniciar sessão na CLI gcloud com a sua identidade federada.

  10. Para inicializar a CLI gcloud, execute o seguinte comando:

    gcloud init
  11. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Verify that billing is enabled for your Google Cloud project.

  13. Enable the Artifact Registry, Cloud Build, Cloud Run, Cloud Run functions, Cloud Storage, and Workflows APIs:

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com run.googleapis.com cloudfunctions.googleapis.com storage.googleapis.com workflows.googleapis.com
  14. Atualize os componentes da CLI do Google Cloud:
    gcloud components update
  15. Se estiver a executar comandos no Cloud Shell, já tem autenticação com a CLI gcloud. Caso contrário, inicie sessão com a sua conta:
    gcloud auth login
  16. Defina a localização predefinida usada neste tutorial:
    gcloud config set project PROJECT_ID
    export REGION=REGION
    gcloud config set functions/region ${REGION}
    gcloud config set run/region ${REGION}
    gcloud config set workflows/location ${REGION}

    Substitua REGION pela localização dos fluxos de trabalho suportados à sua escolha.

  17. Se for o criador do projeto, é-lhe atribuída a função básica de proprietário (roles/owner). Por predefinição, esta função do Identity and Access Management (IAM) inclui as autorizações necessárias para acesso total à maioria dos Google Cloud recursos e pode ignorar este passo.

    Se não for o criador do projeto, as autorizações necessárias têm de ser concedidas no projeto ao principal adequado. Por exemplo, um principal pode ser uma Conta Google (para utilizadores finais) ou uma conta de serviço (para aplicações e cargas de trabalho de computação). Para mais informações, consulte a página Funções e autorizações do destino de eventos.

    Autorizações necessárias

    Para receber as autorizações de que precisa para concluir o tutorial, peça ao seu administrador para lhe conceder as seguintes funções da IAM no seu projeto:

    Para mais informações sobre a atribuição de funções, consulte o artigo Faça a gestão do acesso a projetos, pastas e organizações.

    Também pode conseguir as autorizações necessárias através de funções personalizadas ou outras funções predefinidas.

  18. Quando implementa o fluxo de trabalho, associa-o a uma conta de serviço especificada. Crie uma conta de serviço para os fluxos de trabalho usarem:
    export SERVICE_ACCOUNT=workflows-sa
    gcloud iam service-accounts create ${SERVICE_ACCOUNT}
  19. Por predefinição, todos os serviços do Cloud Run são implementados de forma privada e só podem ser chamados por proprietários do projeto, editores do projeto, administradores do Cloud Run e invocadores do Cloud Run. Para permitir que a conta de serviço chame um serviço do Cloud Run autenticado, conceda a função run.invoker à conta de serviço do Workflows:
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com" \
        --role "roles/run.invoker"
  20. Implemente as primeiras funções do Cloud Run

    Após receber um pedido HTTP, esta função HTTP gera um número aleatório entre 1 e 100 e, em seguida, devolve o número no formato JSON.

    1. Crie um diretório denominado randomgen e altere para o mesmo:

      mkdir ~/randomgen
      cd ~/randomgen
    2. Crie um ficheiro de texto com o nome main.py que contenha o seguinte código Python:

      import functions_framework
      import random
      from flask import jsonify
      
      
      @functions_framework.http
      def randomgen(request):
          randomNum = random.randint(1, 100)
          output = {"random": randomNum}
          return jsonify(output)
    3. Para suportar uma dependência do Flask para o processamento HTTP, crie um ficheiro de texto para o gestor de pacotes pip. Atribua-lhe o nome de ficheiro requirements.txt e adicione o seguinte:

      flask>=1.0.2
      functions-framework==3.0.0
    4. Implemente a função com um acionador HTTP e permita o acesso não autenticado:

      gcloud functions deploy randomgen-function \
          --gen2 \
          --runtime python310 \
          --entry-point=randomgen \
          --trigger-http \
          --allow-unauthenticated

      A implementação da função pode demorar alguns minutos. Em alternativa, pode usar a interface de funções do Cloud Run na Google Cloud consola para implementar a função.

    5. Depois de implementar a função randomgen, pode confirmar a propriedade httpsTrigger.url:

      gcloud functions describe randomgen-function \
          --gen2 \
          --format="value(serviceConfig.uri)"
    6. Guarde o URL. Tem de o adicionar ao ficheiro de origem do fluxo de trabalho nos exercícios posteriores.

    7. Pode experimentar a função com o seguinte comando curl:

      curl $(gcloud functions describe randomgen-function \
          --gen2 \
          --format="value(serviceConfig.uri)")

      É gerado e devolvido um número aleatório.

    Implemente as segundas funções do Cloud Run

    Após receber um pedido HTTP, esta função HTTP extrai o input do corpo JSON, multiplica-o por 2 e devolve o resultado no formato JSON.

    1. Navegue de volta para o diretório inicial:

      cd ~
    2. Crie um diretório denominado multiply e altere para o mesmo:

      mkdir ~/multiply
      cd ~/multiply
    3. Crie um ficheiro de texto com o nome main.py que contenha o seguinte código Python:

      import functions_framework
      from flask import jsonify
      
      
      @functions_framework.http
      def multiply(request):
          request_json = request.get_json()
          output = {"multiplied": 2 * request_json['input']}
          return jsonify(output)
    4. Para suportar uma dependência do Flask para o processamento HTTP, crie um ficheiro de texto para o gestor de pacotes pip. Atribua-lhe o nome de ficheiro requirements.txt e adicione o seguinte:

      flask>=1.0.2
      functions-framework==3.0.0
    5. Implemente a função com um acionador HTTP e permita o acesso não autenticado:

      gcloud functions deploy multiply-function \
          --gen2 \
          --runtime python310 \
          --entry-point=multiply \
          --trigger-http \
          --allow-unauthenticated

      A implementação da função pode demorar alguns minutos. Em alternativa, pode usar a interface de funções do Cloud Run na Google Cloud consola para implementar a função.

    6. Depois de implementar a função multiply, pode confirmar a propriedade httpsTrigger.url:

      gcloud functions describe multiply-function \
          --gen2\
          --format="value(serviceConfig.uri)"
    7. Guarde o URL. Tem de o adicionar ao ficheiro de origem do fluxo de trabalho nos exercícios posteriores.

    8. Pode experimentar a função com o seguinte comando curl:

      curl -X POST MULTIPLY_FUNCTION_URL \
          -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
          -H "Content-Type: application/json" \
          -d '{"input": 5}'

      Deve ser devolvido o número 10.

    Ligue as duas funções do Cloud Run num fluxo de trabalho

    Um fluxo de trabalho é composto por uma série de passos descritos através da sintaxe Workflows, que pode ser escrita no formato YAML ou JSON. Esta é a definição do fluxo de trabalho. Para uma explicação detalhada, consulte a página Referência de sintaxe.

    1. Navegue de volta para o diretório inicial:

      cd ~
    2. Crie um ficheiro de texto com o nome de ficheiro workflow.yaml que contenha o seguinte conteúdo:

      - randomgen_function:
          call: http.get
          args:
              url: RANDOMGEN_FUNCTION_URL
          result: randomgen_result
      - multiply_function:
          call: http.post
          args:
              url: MULTIPLY_FUNCTION_URL
              body:
                  input: ${randomgen_result.body.random}
          result: multiply_result
      - return_result:
          return: ${multiply_result}
      

      Este ficheiro de origem associa as duas funções HTTP e devolve um resultado final.

    3. Depois de criar o fluxo de trabalho, pode implementá-lo, o que o torna pronto para execução.

      gcloud workflows deploy WORKFLOW_NAME \
          --source=workflow.yaml \
          --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com

      Substitua WORKFLOW_NAME por um nome para o seu fluxo de trabalho.

    4. Execute o fluxo de trabalho:

      gcloud workflows run WORKFLOW_NAME

      Uma execução é uma única execução da lógica contida na definição de um fluxo de trabalho. Todas as execuções de fluxos de trabalho são independentes e o dimensionamento rápido dos fluxos de trabalho permite um elevado número de execuções simultâneas.

      Após a execução do fluxo de trabalho, o resultado deve ser semelhante ao seguinte:

      result: '{"body":{"multiplied":120},"code":200,"headers":{"Alt-Svc":"h3-29=\":443\";
      ...
      startTime: '2021-05-05T14:17:39.135251700Z'
      state: SUCCEEDED
      ...
      

    Associe um serviço REST público no fluxo de trabalho

    Atualize o seu fluxo de trabalho existente e associe uma API REST pública (math.js) que possa avaliar expressões matemáticas. Por exemplo, curl https://api.mathjs.org/v4/?'expr=log(56)'.

    Tenha em atenção que, uma vez que implementou o fluxo de trabalho, também o pode editar através da página Fluxos de trabalho na Google Cloud consola.

    1. Edite o ficheiro de origem do fluxo de trabalho e substitua-o pelo seguinte conteúdo:

      - randomgen_function:
          call: http.get
          args:
              url: RANDOMGEN_FUNCTION_URL
          result: randomgen_result
      - multiply_function:
          call: http.post
          args:
              url: MULTIPLY_FUNCTION_URL
              body:
                  input: ${randomgen_result.body.random}
          result: multiply_result
      - log_function:
          call: http.get
          args:
              url: https://api.mathjs.org/v4/
              query:
                  expr: ${"log(" + string(multiply_result.body.multiplied) + ")"}
          result: log_result
      - return_result:
          return: ${log_result}
      

      Esta ação associa o serviço REST externo às funções do Cloud Run e devolve um resultado final.

    2. Implemente o fluxo de trabalho modificado:

      gcloud workflows deploy WORKFLOW_NAME \
          --source=workflow.yaml \
          --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com

    Implemente um serviço do Cloud Run

    Implemente um serviço do Cloud Run que, após receber um pedido HTTP, extraia input do corpo JSON, calcule o respetivo math.floor e devolva o resultado.

    1. Crie um diretório denominado floor e altere para o mesmo:

      mkdir ~/floor
      cd ~/floor
    2. Crie um ficheiro de texto com o nome app.py que contenha o seguinte código Python:

      import json
      import logging
      import os
      import math
      
      from flask import Flask, request
      
      app = Flask(__name__)
      
      
      @app.route('/', methods=['POST'])
      def handle_post():
          content = json.loads(request.data)
          input = float(content['input'])
          return f"{math.floor(input)}", 200
      
      
      if __name__ != '__main__':
          # Redirect Flask logs to Gunicorn logs
          gunicorn_logger = logging.getLogger('gunicorn.error')
          app.logger.handlers = gunicorn_logger.handlers
          app.logger.setLevel(gunicorn_logger.level)
          app.logger.info('Service started...')
      else:
          app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))

    3. No mesmo diretório, crie um ficheiro Dockerfile com o seguinte conteúdo:

      # Use an official lightweight Python image.
      # https://hub.docker.com/_/python
      FROM python:3.7-slim
      
      # Install production dependencies.
      RUN pip install Flask gunicorn
      
      # Copy local code to the container image.
      WORKDIR /app
      COPY . .
      
      # Run the web service on container startup. Here we use the gunicorn
      # webserver, with one worker process and 8 threads.
      # For environments with multiple CPU cores, increase the number of workers
      # to be equal to the cores available.
      CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app

    4. Crie um repositório padrão do Artifact Registry onde pode armazenar a sua imagem de contentor Docker:

      gcloud artifacts repositories create REPOSITORY \
          --repository-format=docker \
          --location=${REGION}

      Substitua REPOSITORY por um nome exclusivo para o repositório.

    5. Crie a imagem de contentor:

      export SERVICE_NAME=floor
      gcloud builds submit --tag ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}
    6. Implemente a imagem do contentor no Cloud Run, garantindo que apenas aceita chamadas autenticadas:

      gcloud run deploy ${SERVICE_NAME} \
          --image ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}:latest \
          --no-allow-unauthenticated

    Quando vir o URL do serviço, a implementação está concluída. Tem de especificar esse URL quando atualizar a definição do fluxo de trabalho.

    Associe o serviço do Cloud Run no fluxo de trabalho

    Atualize o fluxo de trabalho existente e especifique o URL do serviço do Cloud Run.

    1. Navegue de volta para o diretório inicial:

      cd ~
    2. Edite o ficheiro de origem do fluxo de trabalho e substitua-o pelo seguinte conteúdo:

      - randomgen_function:
          call: http.get
          args:
              url: RANDOMGEN_FUNCTION_URL
          result: randomgen_result
      - multiply_function:
          call: http.post
          args:
              url: MULTIPLY_FUNCTION_URL
              body:
                  input: ${randomgen_result.body.random}
          result: multiply_result
      - log_function:
          call: http.get
          args:
              url: https://api.mathjs.org/v4/
              query:
                  expr: ${"log(" + string(multiply_result.body.multiplied) + ")"}
          result: log_result
      - floor_function:
          call: http.post
          args:
              url: CLOUD_RUN_SERVICE_URL
              auth:
                  type: OIDC
              body:
                  input: ${log_result.body}
          result: floor_result
      - create_output_map:
          assign:
            - outputMap:
                randomResult: ${randomgen_result}
                multiplyResult: ${multiply_result}
                logResult: ${log_result}
                floorResult: ${floor_result}
      - return_output:
          return: ${outputMap}
      
      • Substitua RANDOMGEN_FUNCTION_URL pelo URL da sua randomgen função.
      • Substitua MULTIPLY_FUNCTION_URL pelo URL da sua multiply função.
      • Substitua CLOUD_RUN_SERVICE_URL pelo URL do serviço do Cloud Run.

      Isto associa o serviço do Cloud Run no fluxo de trabalho. Tenha em atenção que a chave auth garante que um símbolo de autenticação está a ser transmitido na chamada ao serviço do Cloud Run. Para mais informações, consulte o artigo Faça pedidos autenticados a partir de um fluxo de trabalho.

    3. Implemente o fluxo de trabalho modificado:

      gcloud workflows deploy WORKFLOW_NAME \
          --source=workflow.yaml \
          --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com
    4. Execute o fluxo de trabalho final:

      gcloud workflows run WORKFLOW_NAME

      O resultado deve ser semelhante ao seguinte:

      result: '{"floorResult":{"body":"4","code":200
        ...
        "logResult":{"body":"4.02535169073515","code":200
        ...
        "multiplyResult":{"body":{"multiplied":56},"code":200
        ...
        "randomResult":{"body":{"random":28},"code":200
        ...
      startTime: '2023-11-13T21:22:56.782669001Z'
      state: SUCCEEDED
      

    Parabéns! Implementou e executou um fluxo de trabalho que associa uma série de serviços.

    Para criar fluxos de trabalho mais complexos com expressões, saltos condicionais, codificação ou descodificação Base64, subfluxos de trabalho e muito mais, consulte a referência da sintaxe dos fluxos de trabalho e a vista geral da biblioteca padrão.

    Limpar

    Se criou um novo projeto para este tutorial, elimine o projeto. Se usou um projeto existente e quer mantê-lo sem as alterações adicionadas neste tutorial, elimine os recursos criados para o tutorial.

    Elimine o projeto

    A forma mais fácil de eliminar a faturação é eliminar o projeto que criou para o tutorial.

    Para eliminar o projeto:

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    Elimine recursos de tutoriais

    O que se segue?