Puoi fare riferimento alle best practice elencate qui quando orchestri i tuoi servizi utilizzando i flussi di lavoro.
Questo non è un elenco esaustivo di consigli e non illustra le nozioni di base su come utilizzare i flussi di lavoro. Questo documento presuppone che tu abbia già una conoscenza generale del panorama Google Cloud generale e di Workflows. Per ulteriori informazioni, consulta il Google Cloud Framework di architettura e la Panoramica dei flussi di lavoro.
Seleziona un modello di comunicazione ottimale
Quando progetti un'architettura a microservizi per il deployment di più servizi, puoi scegliere tra i seguenti pattern di comunicazione:
Comunicazione diretta tra servizi
Comunicazione indiretta basata su eventi (nota anche come coreografia)
Configurazione, coordinamento e gestione automatici (noti anche come orchestrazione)
Assicurati di considerare i vantaggi e gli svantaggi di ciascuna delle opzioni precedenti e seleziona un modello ottimale per il tuo caso d'uso. Ad esempio, la comunicazione diretta tra servizi potrebbe essere più semplice da implementare rispetto ad altre opzioni, ma accoppia strettamente i tuoi servizi. Al contrario, un'architettura basata su eventi consente di accoppiare i servizi in modo lasco. Tuttavia, il monitoraggio e il debug potrebbero essere più complicati. Infine, un orchestratore centrale come Workflows, pur essendo meno flessibile, consente di coordinare la comunicazione tra i servizi senza l'accoppiamento stretto della comunicazione diretta tra servizi o la complessità degli eventi coreografati.
Puoi anche combinare i pattern di comunicazione. Ad esempio, nell'orchestrazione basata su eventi, i servizi strettamente correlati vengono gestiti in un'orchestrazione attivata da un evento. Analogamente, puoi progettare un sistema in cui un'orchestrazione genera un messaggio Pub/Sub per un altro sistema orchestrato.
Suggerimenti di carattere generale
Una volta deciso di utilizzare Workflows come orchestratore di servizi, tieni presente i seguenti suggerimenti utili.
Evita di hardcode gli URL
Puoi supportare flussi di lavoro portabili su più ambienti e più facili da gestire evitando gli URL hardcoded. Puoi farlo nei seguenti modi:
Definisci gli URL come argomenti di runtime.
Questa opzione può essere utile quando il flusso di lavoro viene invocato tramite una libreria client o l'API. Tuttavia, questo non funzionerà se il flusso di lavoro viene attivato da un evento di Eventarc e l'unico argomento che può essere passato è il payload dell'evento.
Esempio
main: params: [args] steps: - init: assign: - url1: ${args.urls.url1} - url2: ${args.urls.url2}
Quando esegui il flusso di lavoro, puoi specificare gli URL. Ad esempio:
gcloud workflows run multi-env --data='{"urls":{"url1": "URL_ONE", "url2": "URL_TWO"}}'
Utilizza le variabili di ambiente e crea un flusso di lavoro configurato dinamicamente in base all'ambiente in cui viene eseguito il deployment. In alternativa, crea un workflow che può essere riutilizzato come modello e configurato in base a variabili di ambiente gestite distintamente.
Utilizza una tecnica di sostituzione che ti consente di creare un unico file di definizione del flusso di lavoro, ma di implementare le varianti utilizzando uno strumento che sostituisce i segnaposto nel flusso di lavoro. Ad esempio, puoi utilizzare Cloud Build per eseguire il deployment di un flusso di lavoro e nel file di configurazione di Cloud Build aggiungere un passaggio per sostituire gli URL segnaposto nel flusso di lavoro.
Esempio
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']
Poi puoi sostituire i valori delle variabili in fase di compilazione. Ad esempio:
gcloud builds submit --config cloudbuild.yaml \ --substitutions=_ENV=staging,_URL1="URL_ONE",_URL2="URL_TWO"
Per ulteriori informazioni, consulta Inviare una build tramite interfaccia a riga di comando e API.
In alternativa, puoi utilizzare Terraform per eseguire il provisioning dell'infrastruttura e definire un file di configurazione che crei flussi di lavoro per ogni ambiente utilizzando le variabili di input.
Esempio
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 le variabili vengono dichiarate nel modulo principale della configurazione, possono essere assegnati valori in diversi modi. Ad esempio:
terraform apply -var="project_id=PROJECT_ID" -var="url1=URL_ONE" -var="url2=URL_TWO"
Utilizza il connettore Secret Manager per archiviare e recuperare in modo sicuro gli URL in Secret Manager.
Utilizzare i passaggi nidificati
Ogni workflow deve avere almeno un passaggio.
Per impostazione predefinita, Workflows tratta i passaggi come se fossero in un elenco ordinato e li esegue uno alla volta fino a quando non sono stati eseguiti tutti. Logicamente, alcuni passaggi devono essere raggruppati e puoi utilizzare un blocco steps
per nidificare una serie di passaggi. Questa opzione è utile perché ti consente di indicare il
passaggio atomico corretto per elaborare un insieme di passaggi.
Esempio
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]}
Inserire un a capo nelle espressioni
Tutte le espressioni devono iniziare con un $
e essere racchiuse tra parentesi graffe:
${EXPRESSION}
Per evitare problemi di analisi di YAML, puoi racchiudere le espressioni tra virgolette. Ad esempio, le espressioni contenenti due punti possono causare un comportamento imprevisto quando i due punti vengono interpretati come una definizione di una mappa. Per risolvere il problema, racchiudi l'espressione YAML tra virgolette singole:
'${"Name: " + myVar}'
Puoi anche utilizzare espressioni che si estendono su più righe. Ad esempio, potresti dover inserire una query SQL tra virgolette quando utilizzi il connettore BigQuery di Workflows.
Esempio
- 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
Per l'intera definizione del flusso di lavoro, consulta Eseguire più job BigQuery in parallelo.
Utilizzare le chiamate dichiarative
Utilizza Workflows per chiamare i servizi dal flusso di lavoro stesso e gestire i risultati, nonché per eseguire attività semplici come effettuare una chiamata HTTP. I flussi di lavoro possono richiamare servizi, analizzare le risposte e costruire input per altri servizi collegati. La chiamata di un servizio ti consente di evitare le complicazioni di chiamate aggiuntive, dipendenze aggiuntive e servizi che chiamano servizi. Valuta la possibilità di sostituire i servizi privi di logica di business con chiamate API declarative e utilizza Workflows per astrarre la complessità.
Tuttavia, devi creare servizi per svolgere qualsiasi attività troppo complessa per Workflows, ad esempio l'implementazione di logica di business riutilizzabile, calcoli complessi o trasformazioni non supportate dalle espressioni di Workflows e dalla relativa libreria standard. In genere, un caso complicato è più facile da implementare nel codice anziché utilizzando YAML o JSON e la sintassi di Workflows.
Memorizza solo ciò che ti serve
Tieni sotto controllo il consumo di memoria per non riscontrare limiti di risorse o un errore che lo indichi, ad esempio ResourceLimitError
, MemoryLimitExceededError
o ResultSizeLimitExceededError
.
Scegli con attenzione cosa memorizzare nelle variabili, filtrando e memorizzando solo ciò che ti serve. Se un servizio restituisce un payload troppo grande, utilizza una funzione separata per effettuare la chiamata per tuo conto e restituire solo ciò che è necessario.
Puoi liberare memoria svuotando le variabili. Ad esempio, potresti voler liberare la memoria necessaria per i passaggi successivi. In alternativa, potresti avere chiamate con risultati che non ti interessano e puoi ometterli del tutto.
Puoi cancellare una variabile assegnando null
. In YAML, puoi anche assegnare un valore vuoto o ~
a una variabile. In questo modo viene identificata la memoria che può essere recuperata in sicurezza.
Esempio
- step: assign: - bigVar:
Utilizzare flussi di lavoro secondari e flussi di lavoro esterni
Puoi utilizzare i flussi di lavoro secondari per definire un frammento di logica o un insieme di passaggi da chiamare più volte, semplificando la definizione del flusso di lavoro. I sottoprocessi sono simili a una funzione o routine in un linguaggio di programmazione. Possono accettare parametri e restituire valori, consentendoti di creare flussi di lavoro più complessi con una gamma più ampia di applicazioni.
Tieni presente che i flussi di lavoro secondari sono locali per la definizione del flusso di lavoro e non possono essere riutilizzati in altri flussi di lavoro. Tuttavia, puoi chiamare i flussi di lavoro da altri flussi di lavoro. I connettori di flussi di lavoro possono aiutarti a farlo. Per maggiori informazioni, consulta le panoramiche dei connettori per l'API Workflow Executions e l'API Workflows.
Utilizzare i connettori di Workflows
Workflows fornisce una serie di connettori che semplificano l'accesso ad altri Google Cloud prodotti all'interno di un flusso di lavoro. I connettori simplificano le chiamate ai servizi perché gestiscono la formattazione delle richieste per te, fornendo metodi e argomenti in modo da non dover conoscere i dettagli di un'Google Cloud API. I connettori hanno anche un comportamento integrato per gestire i nuovi tentativi e le operazioni a lunga esecuzione, in modo da evitare di eseguire l'iterazione e attendere il completamento delle chiamate. I connettori si occupano di tutto.
Se devi chiamare un' Google Cloud API, controlla prima se esiste un connettore Workflows per l'API. Se non vedi un connettore per un Google Cloud prodotto, puoi richiedere.
Scopri come utilizzare un connettore e, per un riferimento dettagliato dei connettori disponibili, consulta Guida ai connettori.
Eseguire i passaggi del flusso di lavoro in parallelo
Sebbene Workflows possa eseguire i passaggi in sequenza, puoi anche eseguire passaggi indipendenti in parallelo. In alcuni casi, questa operazione può velocizzare notevolmente l'esecuzione del flusso di lavoro. Per ulteriori informazioni, consulta Eseguire i passaggi del flusso di lavoro in parallelo.
Applica i tentativi e il pattern saga
Progetta flussi di lavoro resilienti in grado di gestire errori di servizio sia temporanei che permanenti. Gli errori per i flussi di lavoro potrebbero essere generati, ad esempio, da richieste HTTP, funzioni o connettori non riusciti o dal codice del tuo flusso di lavoro. Aggiungi la gestione degli errori e i tentativi ripetuti in modo che un errore in un passaggio non causi il fallimento dell'intero flusso di lavoro.
- Puoi generare errori personalizzati
utilizzando la sintassi
raise
. - Puoi rilevare gli errori utilizzando un blocco
try/except
. - Puoi riprovare i passaggi utilizzando un blocco
try/retry
e definire il numero massimo di tentativi di ripetizione.
Alcune transazioni aziendali interessano più servizi, quindi è necessario un meccanismo per implementare transazioni che coinvolgono più servizi. Il pattern di progettazione saga è un modo per gestire la coerenza dei dati tra i microservizi in scenari di transazioni distribuite. Una saga è una sequenza di transazioni che pubblica un evento per ogni transazione e attiva la transazione successiva. Se una transazione non va a buon fine, la saga esegue transazioni di compensazione che contrastano gli errori precedenti nella sequenza. Prova il tutorial su ripetizioni e pattern Saga nei flussi di lavoro su GitHub.
Utilizzare i callback per attendere
I richiami consentono alle esecuzioni del flusso di lavoro di attendere che un altro servizio invii una richiesta all'endpoint di callback, che riprende l'esecuzione del flusso di lavoro.
Con i callback, puoi segnalare al tuo flusso di lavoro che si è verificato un evento specifico e attendere questo evento senza polling. Ad esempio, puoi creare un flusso di lavoro che ti invii una notifica quando un prodotto è di nuovo disponibile o quando un articolo è stato spedito oppure che attende di consentire l'interazione umana, ad esempio la revisione di un ordine o la convalida di una traduzione. Puoi anche aspettare gli eventi utilizzando i callback e gli attivatori Eventarc.
Orchestrare job a lunga esecuzione
Se devi eseguire carichi di lavoro di elaborazione batch di lunga durata, puoi utilizzare Batch o job Cloud Run e puoi utilizzare Workflows per gestire i servizi. In questo modo puoi combinare i vantaggi e eseguire il provisioning e l'orchestrazione dell'intero processo in modo efficiente.
Batch è un servizio completamente gestito che consente di pianificare, inserire in coda ed eseguire carichi di lavoro batch su istanze di macchine virtuali (VM) Compute Engine. Puoi utilizzare il connettore Workflows per Batch per pianificare ed eseguire un job Batch. Per maggiori dettagli, prova il tutorial.
I job Cloud Run vengono utilizzati per eseguire codice che esegue un'operazione (un job) e si arresta al termine dell'operazione. Workflows ti consente di eseguire job Cloud Run all'interno di un flusso di lavoro per eseguire elaborazioni di dati più complesse o orchestrare un sistema di job esistenti. Prova il tutorial che dimostra come utilizzare i flussi di lavoro per eseguire un job Cloud Run.
Containerizza le attività a lunga esecuzione
Puoi automatizzare l'esecuzione di un container a lungo termine utilizzando Workflows e Compute Engine. Ad esempio, puoi eseguire il contenimento di un'attività a lungo termine in modo che possa essere eseguita ovunque, quindi eseguire il contenitore su una VM Compute Engine per la durata massima di un'esecuzione del flusso di lavoro (un anno).
Con i flussi di lavoro, puoi automatizzare la creazione della VM, l'esecuzione del contenitore sulla VM e l'eliminazione della VM. In questo modo puoi utilizzare un server ed eseguire un contenitore, ma la complessità della gestione di entrambi viene riassunta e può essere utile se riscontri limitazioni di tempo durante l'utilizzo di un servizio come Cloud Run Functions o Cloud Run. Prova il tutorial sui contenitori a lungo termine con Workflows e Compute Engine su GitHub.
Eseguire strumenti a riga di comando da Workflows
Cloud Build è un servizio che esegue le build Google Cloud come una serie di passaggi di build, dove ogni passaggio viene eseguito in un container Docker. L'esecuzione di passaggi di build è analoga all'esecuzione di comandi in uno script.
Google Cloud CLI include gli strumenti a riga di comando gcloud
, bq
e
kubectl
, ma non esiste un modo diretto per eseguire i comandi gcloud CLI
da Workflows. Tuttavia, Cloud Build fornisce immagini container che includono la CLI gcloud. Puoi eseguire i comandi gcloud CLI in questi container da un passaggio Cloud Build e puoi creare questo passaggio in Workflows utilizzando il connettore Cloud Build.
Esempio
Esegui gcloud
in un flusso di lavoro:
Run kubectl
in a workflow:
Utilizzare Terraform per creare il flusso di lavoro
Terraform è uno strumento Infrastructure as Code che consente di creare, modificare e migliorare in modo prevedibile l'infrastruttura cloud utilizzando il codice.
Puoi definire ed eseguire il deployment di un flusso di lavoro utilizzando la risorsa Terraform
google_workflows_workflow
. Per ulteriori informazioni, consulta
Creare un flusso di lavoro utilizzando Terraform.
Per aiutarti a gestire e mantenere i flussi di lavoro di grandi dimensioni, puoi creare il tuo flusso di lavoro in un file YAML separato e importarlo in Terraform utilizzando la funzione templatefile
che legge un file in un determinato percorso e ne esegue il rendering dei contenuti come modello.
Esempio
# 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",{}) }
Analogamente, se hai un flusso di lavoro principale che chiama più sottoflussi di lavoro, puoi
definire il flusso di lavoro principale e i sottoflussi di lavoro in file separati e utilizzare la
funzione templatefile
per importarli.
Esempio
# 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",{} )]) }
Tieni presente che, se fai riferimento ai numeri di riga durante il debug di un flusso di lavoro, tutti i file YAML importati tramite il file di configurazione di Terraform vengono uniti e di cui viene eseguito il deployment come un unico flusso di lavoro.
Esegui il deployment di un workflow da un repository Git
Cloud Build utilizza trigger di build per abilitare l'automazione CI/CD. Puoi configurare gli attivatori in modo che ascoltino gli eventi in arrivo, ad esempio quando viene eseguito il push di un nuovo commit in un repository o quando viene avviata una richiesta di pull, quindi eseguire automaticamente una build quando arrivano nuovi eventi.
Puoi utilizzare un trigger di Cloud Build per avviare automaticamente una build e implementare un flusso di lavoro da un repository Git. Puoi configurare l'attivatore per eseguire il deployment del flusso di lavoro in caso di qualsiasi modifica al repository di origine o solo quando la modifica soddisfa determinati criteri.
Questo approccio può aiutarti a gestire il ciclo di vita del deployment. Ad esempio, puoi eseguire il deployment delle modifiche a un flusso di lavoro in un ambiente di staging, eseguire test su quell'ambiente e poi lanciare queste modifiche in modo incrementale nell'ambiente di produzione. Per ulteriori informazioni, consulta Eseguire il deployment di un flusso di lavoro da un repository Git utilizzando Cloud Build.
Ottimizzare l'utilizzo
Il costo per l'esecuzione di un flusso di lavoro è minimo. Tuttavia, per un utilizzo di alto volume, applica le seguenti linee guida per ottimizzare l'utilizzo e ridurre i costi:
Anziché utilizzare domini personalizzati, assicurati che le chiamate ai servizi Google Cloud utilizzino
*.appspot.com
,*.cloud.goog
,*.cloudfunctions.net
o*.run.app
in modo che ti vengano addebitati i passaggi interni e non esterni.Applica un criterio di ripetizione personalizzato che bilanci le esigenze di latenza e affidabilità con i costi. I tentativi più frequenti riducono la latenza e aumentano l'affidabilità, ma possono anche aumentare i costi.
Quando utilizzi connettori che aspettano operazioni di lunga durata, imposta un criterio di polling personalizzato che ottimizza la latenza in base al costo. Ad esempio, se prevedi che un'operazione richieda più di un'ora, ti consigliamo di utilizzare un criterio che esegua inizialmente il polling dopo un minuto in caso di errore immediato e poi ogni 15 minuti.
Combina le compiti in un unico passaggio.
Evita di utilizzare un numero eccessivo di passaggi
sys.log
. Ti consigliamo di utilizzare invece il registro delle chiamate.
Riepilogo delle best practice
La tabella seguente riassume i suggerimenti generali e le best practice consigliate in questo documento.