Consulte as práticas recomendadas listadas aqui ao orquestrar seus serviços usando o Workflows.
Esta não é uma lista completa de recomendações e não ensina os conceitos básicos de como usar o Workflows. Para seguir este documento, é necessário ter uma compreensão geral do cenário geral do Google Cloud e dos Workflows. Para mais informações, consulte o Framework de arquitetura do Google Cloud e a Visão geral de fluxos de trabalho.
Selecionar o padrão de comunicação ideal
Ao projetar uma arquitetura de microsserviços para implantar vários serviços, é possível escolher entre os seguintes padrões de comunicação:
Comunicação direta de serviço a serviço
Comunicação indireta orientada a eventos (também conhecida como coreografia)
Configuração, coordenação e gerenciamento automatizados (também conhecidos como orquestração)
Considere as vantagens e desvantagens de cada uma das opções anteriores e selecione um padrão ideal para seu caso de uso. Por exemplo, a comunicação direta de serviço a serviço pode ser mais simples de implementar do que outras opções, mas acopla seus serviços de forma rígida. Por outro lado, com uma arquitetura orientada a eventos, você consegue fazer o acoplamento flexível dos serviços. No entanto, o monitoramento e a depuração podem ser mais complicados. Por fim, um orquestrador central como o Workflows, embora seja menos flexível, permite coordenar a comunicação entre serviços sem o acoplamento estreito da comunicação direta entre serviços ou a complexidade de eventos coreografados.
Também é possível combinar padrões de comunicação. Por exemplo, na orquestração orientada a eventos, serviços intimamente relacionados são gerenciados em uma orquestração acionada por um evento. Da mesma forma, é possível projetar um sistema em que uma orquestração resulte em uma mensagem do Pub/Sub para outro sistema orquestrado.
Dicas gerais
Depois de decidir usar o Workflows como seu orquestrador de serviço, lembre as dicas úteis a seguir.
Evite fixar URLs no código
É possível oferecer suporte a fluxos de trabalho portáteis em vários ambientes e mais fáceis de manter, evitando URLs fixados no código. É possível fazer isso das seguintes maneiras:
Defina URLs como argumentos de ambiente de execução.
Isso pode ser útil quando seu fluxo de trabalho é invocado por uma biblioteca de cliente ou pela API. No entanto, isso não vai funcionar se o fluxo de trabalho for acionado por um evento do Eventarc e o único argumento que puder ser transmitido for o payload do evento.
Exemplo
main: params: [args] steps: - init: assign: - url1: ${args.urls.url1} - url2: ${args.urls.url2}
Ao executar o fluxo de trabalho, é possível especificar os URLs. Por exemplo:
gcloud workflows run multi-env --data='{"urls":{"url1": "URL_ONE", "url2": "URL_TWO"}}'
Use variáveis de ambiente e crie um fluxo de trabalho que é configurado dinamicamente, dependendo do ambiente em que ele é implantado. Outra opção é criar um fluxo de trabalho que pode ser reutilizado como um modelo e configurado de acordo com as variáveis de ambiente mantidas separadamente.
Use uma técnica de substituição que permita criar um único arquivo de definição de fluxo de trabalho e implante variantes usando uma ferramenta que substitui marcadores de posição. Por exemplo, é possível usar o Cloud Build para implantar um fluxo de trabalho e, no arquivo de configuração do Cloud Build, adicionar uma etapa para substituir URLs de marcador no fluxo de trabalho.
Exemplo
steps: ‐ id: 'replace-urls' name: 'gcr.io/cloud-builders/gcloud' entrypoint: bash args: - -c - | sed -i -e "s~REPLACE_url1~$_URL1~" workflow.yaml sed -i -e "s~REPLACE_url2~$_URL2~" workflow.yaml ‐ id: 'deploy-workflow' name: 'gcr.io/cloud-builders/gcloud' args: ['workflows', 'deploy', 'multi-env-$_ENV', '--source', 'workflow.yaml']
Em seguida, você pode substituir os valores de variáveis no tempo de build. Exemplo:
gcloud builds submit --config cloudbuild.yaml \ --substitutions=_ENV=staging,_URL1="URL_ONE",_URL2="URL_TWO"
Para mais informações, consulte Enviar um build via CLI e API.
Se preferir, use o Terraform para provisionar sua infraestrutura e definir um arquivo de configuração que crie fluxos de trabalho para cada ambiente usando variáveis de entrada.
Exemplo
variable "project_id" { type = string } variable "url1" { type = string } variable "url2" { type = string } locals { env = ["staging", "prod"] } # Define and deploy staging and production workflows resource "google_workflows_workflow" "multi-env-workflows" { for_each = toset(local.env) name = "multi-env-${each.key}" project = var.project_id region = "us-central1" source_contents = templatefile("${path.module}/workflow.yaml", { url1 : "${var.url1}-${each.key}", url2 : "${var.url2}-${each.key}" }) }
Quando variáveis são declaradas no módulo raiz da configuração, elas podem receber valores atribuídos de várias maneiras. Por exemplo:
terraform apply -var="project_id=PROJECT_ID" -var="url1=URL_ONE" -var="url2=URL_TWO"
Use o conector do Secret Manager para armazenar URLs com segurança no Secret Manager e recuperá-los.
Usar etapas aninhadas
Todo fluxo de trabalho precisa ter pelo menos uma etapa.
Por padrão, o Workflows trata as etapas como se estivessem em uma lista
ordenada e as executa uma de cada vez até que todas sejam executadas. Logicamente, algumas etapas precisam ser agrupadas, e você pode usar um bloco steps
para aninhar uma série de etapas. Isso é prático, porque permite apontar para a etapa atômica correta para processar um conjunto de etapas.
Exemplo
main: params: [input] steps: - callWikipedia: steps: - checkSearchTermInInput: switch: - condition: ${"searchTerm" in input} assign: - searchTerm: ${input.searchTerm} next: readWikipedia - getCurrentDate: call: http.get args: url: https://timeapi.io/api/Time/current/zone?timeZone=Europe/Amsterdam result: currentDate - setFromCallResult: assign: - searchTerm: ${currentDate.body.dayOfWeek} - readWikipedia: call: http.get args: url: https://en.wikipedia.org/w/api.php query: action: opensearch search: ${searchTerm} result: wikiResult - returnOutput: return: ${wikiResult.body[1]}
Unir expressões
Todas as expressões precisam começar com
um $
e estar entre chaves:
${EXPRESSION}
Para evitar problemas de análise YAML, coloque as expressões entre aspas. Por exemplo, expressões que contêm dois-pontos podem causar um comportamento inesperado quando os dois pontos são interpretados como a definição de um mapa. Para resolver esse problema, coloque a expressão YAML entre aspas simples:
'${"Name: " + myVar}'
Também é possível usar expressões que abranjam várias linhas. Por exemplo, talvez seja necessário colocar uma consulta SQL entre aspas ao usar o conector de Workflows do BigQuery.
Exemplo
- runQuery: call: googleapis.bigquery.v2.jobs.query args: projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")} body: useLegacySql: false useQueryCache: false timeoutMs: 30000 # Find top 100 titles with most views on Wikipedia query: ${ "SELECT TITLE, SUM(views) FROM `bigquery-samples.wikipedia_pageviews." + table + "` WHERE LENGTH(TITLE) > 10 GROUP BY TITLE ORDER BY SUM(VIEWS) DESC LIMIT 100" } result: queryResult
Para ver toda a definição do fluxo de trabalho, acesse Executar vários jobs do BigQuery em paralelo.
Usar chamadas declarativas
Use o Workflows para chamar serviços do próprio fluxo de trabalho, processar os resultados e executar tarefas simples, como fazer uma chamada HTTP. Workflows podem invocar serviços, analisar respostas e criar entradas para outros serviços conectados. Chamar um serviço permite evitar as complicações de invocações extras, dependências extras e serviços que chamam serviços. Considere substituir serviços sem lógica de negócios por chamadas de API declarativas e use Workflows para abstrair a complexidade.
No entanto, é preciso criar serviços para fazer qualquer trabalho muito complexo para o Workflows. Por exemplo, implementar lógica de negócios reutilizável, cálculos complexos ou transformações que não sejam compatíveis com expressões do Workflows e a biblioteca padrão. Em geral, um caso complicado é mais fácil de implementar no código do que usar YAML ou JSON e a sintaxe de fluxos de trabalho.
Armazene apenas o que precisa
Mantenha o consumo de memória sob controle para não encontrar
limites de recursos ou um erro que indique
isso, como ResourceLimitError
, MemoryLimitExceededError
ou
ResultSizeLimitExceededError
.
Seja seletivo sobre o que você armazena nas variáveis, filtrando e armazenando apenas o que você precisa. Se um serviço retornar um payload muito grande, use uma função separada para fazer a chamada para você e retornar apenas o que é necessário.
Libere memória limpando as variáveis. Por exemplo, libere memória necessária para as etapas subsequentes. Ou você pode ter chamadas com resultados que não importam e pode omitir esses resultados completamente.
É possível limpar uma variável atribuindo null
. No YAML, você também pode atribuir um valor vazio ou ~
a uma variável. Isso identifica a memória que pode ser recuperada com segurança.
Exemplo
- step: assign: - bigVar:
Usar subfluxos de trabalho e fluxos de trabalho externos
É possível usar subfluxos de trabalho para definir uma parte da lógica ou um conjunto de etapas que você quer chamar várias vezes, simplificando a definição do fluxo de trabalho. Os subfluxos de trabalho são semelhantes a uma função ou rotina em uma linguagem de programação. Elas podem aceitar parâmetros e retornar valores, permitindo que você crie fluxos de trabalho mais complexos com uma gama mais ampla de aplicativos.
Os subfluxos de trabalho são locais à definição de fluxo de trabalho e não podem ser reutilizados em outros fluxos de trabalho. No entanto, é possível chamar fluxos de trabalho de outros fluxos. Os conectores do Workflows podem ajudar você com isso. Para mais informações, consulte as visões gerais dos conectores da API Workflow Executions e da API Workflows.
Usar conectores do Workflows
O Workflows fornece vários connectors que facilitam o acesso a outros produtos do Google Cloud em um fluxo de trabalho. Os conectores simplificam a chamada de serviços porque gerenciam a formatação das solicitações para você, fornecendo métodos e argumentos para que você não precise conhecer os detalhes de uma API do Google Cloud. Os conectores também têm um comportamento integrado para processar novas tentativas e operações de longa duração, para evitar iterar e aguardar a conclusão das chamadas. Os conectores fazem isso por você.
Se você precisar chamar uma API do Google Cloud, primeiro verifique se existe um conector de Workflows para ela. Se você não encontrar um conector para um produto do Google Cloud, solicite-o.
Saiba como usar um conector e, para ver uma referência detalhada dos conectores disponíveis, consulte a Referência de conectores.
Executar etapas do fluxo de trabalho em paralelo
Os fluxos de trabalho podem executar etapas sequencialmente, mas também é possível executar etapas independentes em paralelo. Em alguns casos, isso pode acelerar significativamente a execução do fluxo de trabalho. Para mais informações, consulte Executar etapas do fluxo de trabalho em paralelo.
Aplicar novas tentativas e o padrão saga
Projete fluxos de trabalho que sejam resilientes e possam lidar com falhas de serviço transitórias e permanentes. Os erros dos Workflows podem ser gerados, por exemplo, por solicitações HTTP, funções, conectores com falha ou gerados pelo seu próprio código de fluxo de trabalho. Adicione tratamento de erros e novas tentativas para que uma falha em uma etapa não cause falha em todo o fluxo de trabalho.
- Você pode gerar erros personalizados
usando a sintaxe
raise
. - É possível detectar erros usando
um bloco
try/except
. - É possível repetir as etapas usando um
bloco
try/retry
e definir o número máximo de novas tentativas.
Algumas transações comerciais abrangem vários serviços. Por isso, você precisa de um mecanismo para implementar transações que abrangem serviços. O padrão de design de saga é uma forma de gerenciar a consistência de dados em microsserviços em cenários de transações distribuídas. Uma saga é uma sequência de transações que publica um evento para cada transação e aciona a próxima transação. Se uma transação falha, a saga executa transações de compensação que anulam as falhas anteriores na sequência. Confira o tutorial de novas tentativas e padrão saga no Workflows trabalho (em inglês) no GitHub.
Usar callbacks para aguardar
Os callbacks permitem que as execuções de fluxo de trabalho aguardem até que outro serviço faça uma solicitação ao endpoint de callback. Essa solicitação retoma a execução do fluxo de trabalho.
Com callbacks, é possível sinalizar ao fluxo de trabalho que um evento especificado ocorreu e aguardar esse evento sem pesquisas. Por exemplo, é possível criar um fluxo de trabalho que notifica quando um produto volta ao estoque ou quando um item é enviado, ou que aguarda a interação humana, como a revisão de um pedido ou a validação de uma tradução. Você também pode aguardar eventos usando callbacks e gatilhos do Eventarc.
Orquestrar jobs de longa duração
Se você precisar executar cargas de trabalho de processamento em lote de longa duração, use jobs em lote ou do Cloud Run e use os Workflows para gerenciar os serviços. Isso permite combinar vantagens e provisionar e orquestrar com eficiência todo o processo.
O Batch é um serviço totalmente gerenciado que permite programar, enfileirar e executar cargas de trabalho em lote em instâncias de máquina virtual (VM) do Compute Engine. É possível usar o conector de fluxos de trabalho para o Batch se quiser programar e executar um job no Batch. Para mais detalhes, confira o tutorial.
Os jobs do Cloud Run são usados para executar um código que executa um trabalho (um job) e é encerrado quando o trabalho é concluído. Ele permite executar jobs do Cloud Run como parte de um fluxo de trabalho para realizar processamentos de dados mais complexos ou orquestrar um sistema de jobs atuais. Siga o tutorial que demonstra como usar o Workflows para executar um job do Cloud Run.
Conteinerizar tarefas de longa duração
É possível automatizar a execução de um contêiner de longa duração usando o Workflows e o Compute Engine. Por exemplo, é possível conteinerizar uma tarefa de longa duração para que ela possa ser executada em qualquer lugar e, em seguida, executar o contêiner em uma VM do Compute Engine pela duração máxima de uma execução de fluxo de trabalho (um ano).
Com o Workflows, é possível automatizar a criação da VM, a execução do contêiner na VM e a exclusão da VM. Isso permite que você use um servidor e execute um contêiner, mas simplifica a complexidade de gerenciar ambos e pode ser útil caso você encontre limitações de tempo ao usar um serviço como o Cloud Functions ou o Cloud Run. Confira o tutorial Contêineres de longa duração com o Workflows e o Compute Engine no GitHub.
Executar ferramentas de linha de comando no Workflows
O Cloud Build é um serviço que executa seus builds no Google Cloud como uma série de etapas de compilação. Cada uma delas é executada em um contêiner do Docker. Executar etapas de build é análogo à execução de comandos em um script.
A Google Cloud CLI inclui as ferramentas de linha de comando gcloud
, gsutil
, bq
e
kubectl
, mas não há uma maneira direta de executar comandos da CLI gcloud
a partir do Workflows. No entanto, o Cloud Build
fornece imagens de contêiner que incluem a CLI gcloud. É possível executar
comandos da CLI gcloud nesses contêineres a partir de uma etapa do Cloud Build
e criá-la no Workflows usando o
conector do Cloud Build.
Exemplo
Execute gcloud
em um fluxo de trabalho:
Run kubectl
in a workflow:
Usar o Terraform para criar seu fluxo de trabalho
O Terraform é uma ferramenta de infraestrutura como código que permite criar, alterar e melhorar de maneira previsível suainfraestrutura em nuvemem usando código.
É possível definir e implantar um fluxo de trabalho usando o recurso
google_workflows_workflow
do Terraform. Para mais informações, acesse
Criar um fluxo de trabalho usando o Terraform.
Para gerenciar e manter grandes fluxos de trabalho, crie seu fluxo de trabalho
em um arquivo YAML separado e importe esse arquivo para o Terraform usando a
função templatefile
,
que lê um arquivo em um determinado caminho e renderiza o conteúdo dele como um modelo.
Exemplo
# Define a workflow resource "google_workflows_workflow" "workflows_example" { name = "sample-workflow" region = var.region description = "A sample workflow" service_account = google_service_account.workflows_service_account.id # Import main workflow YAML file source_contents = templatefile("${path.module}/workflow.yaml",{}) }
Da mesma forma, se você tiver um fluxo de trabalho principal chamando vários subfluxos de trabalho, poderá
definir o fluxo de trabalho principal e os subfluxos de trabalho em arquivos separados e usar a
função templatefile
para importá-los.
Exemplo
# Define a workflow resource "google_workflows_workflow" "workflows_example" { name = "sample-workflow" region = var.region description = "A sample workflow" service_account = google_service_account.workflows_service_account.id # Import main workflow and subworkflow YAML files source_contents = join("", [ templatefile( "${path.module}/workflow.yaml",{} ), templatefile( "${path.module}/subworkflow.yaml",{} )]) }
Se você estiver se referindo a números de linha ao depurar um fluxo de trabalho, todos os arquivos YAML importados por meio do arquivo de configuração do Terraform serão mesclados e implantados como um único fluxo de trabalho.
Implantar um fluxo de trabalho de um repositório Git
O Cloud Build usa gatilhos de build para permitir a automação de CI/CD. É possível configurar gatilhos para detectar eventos recebidos, como quando uma nova confirmação é enviada para um repositório ou quando uma solicitação de envio é iniciada. Depois disso, uma versão é executada automaticamente quando novos eventos chegam.
É possível usar um gatilho do Cloud Build para iniciar automaticamente um build e implantar um fluxo de trabalho de um repositório Git. É possível configurar o gatilho para implantar o fluxo de trabalho em qualquer alteração no repositório de origem ou implantar o fluxo de trabalho somente quando a alteração corresponder a critérios específicos.
Essa abordagem pode ajudar você a gerenciar o ciclo de vida da implantação. Por exemplo, é possível implantar alterações em um fluxo de trabalho em um ambiente de preparo, executar testes nesse ambiente e lançar gradualmente essas alterações no ambiente de produção. Para mais informações, consulte Implantar um fluxo de trabalho de um repositório Git usando o Cloud Build.
Otimizar o uso
O custo de execução de um fluxo de trabalho é mínimo. No entanto, em casos de uso de alto volume, aplique as diretrizes a seguir para otimizar o uso e reduzir os custos:
Em vez de usar domínios personalizados, verifique se todas as chamadas para os serviços do Google Cloud usam
*.appspot.com
,*.cloud.goog
,*.cloudfunctions.net
ou*.run.app
. Assim, você será cobrado por etapas internas e não externas.Aplique uma política de nova tentativa personalizada que equilibre os custos e as necessidades de latência e confiabilidade. Tentativas mais frequentes diminuem a latência e aumentam a confiabilidade, mas também podem aumentar os custos.
Ao usar conectores que aguardam operações de longa duração, defina uma política de pesquisa personalizada que otimize a latência para o custo. Por exemplo, se você espera que uma operação leve mais de uma hora, convém ter uma política que inicialmente pesquise após um minuto em caso de falha imediata e, depois, a cada 15 minutos.
Combine as atribuições em uma única etapa.
Evite o uso excessivo de
sys.log
etapas. Considere usar o registro de chamadas.
Resumo das práticas recomendadas
A tabela a seguir resume as dicas gerais e as práticas recomendadas recomendadas neste documento.
A seguir
- Práticas recomendadas de segurança
- Visão geral da depuração
- Resolver problemas
- Problemas conhecidos do Workflows