ID regione
Il REGION_ID è un codice abbreviato che Google assegna
in base alla regione selezionata quando crei l'app. Il codice non
corrisponde a un paese o a una provincia, anche se alcuni ID regione possono sembrare
simili ai codici di paesi e province di uso comune. Per le app create dopo
febbraio 2020, REGION_ID.r è incluso negli
URL App Engine. Per le app esistenti create prima di questa data, l'ID regione è facoltativo nell'URL.
Scopri di più sugli ID regione.
I microservizi su App Engine in genere si chiamano a vicenda utilizzando API RESTful basate su HTTP. È anche possibile richiamare i microservizi in background utilizzando le code di attività e si applicano i principi di progettazione delle API descritti qui. È importante seguire determinati pattern per garantire che l'applicazione basata su microservizi sia stabile, sicura e funzioni correttamente.
Utilizzo di contratti solidi
Uno degli aspetti più importanti delle applicazioni basate su microservizi è la possibilità di eseguire il deployment dei microservizi in maniera totalmente indipendente l'uno dall'altro. Per raggiungere questa indipendenza, ciascun microservizio deve fornire un contratto ben definito e soggetto al controllo delle versioni ai propri client, che sono altri microservizi. I singoli servizi non devono interrompere questi contratti sottoposti al controllo delle versioni finché non viene appurato che nessun altro microservizio fa affidamento su uno di tali contratti. Tieni presente che altri microservizi potrebbero dover eseguire il rollback a una versione precedente del codice che richiede un contratto precedente, per cui è importante tenerne conto nei criteri di deprecazione e disattivazione.
Probabilmente, l'aspetto organizzativo più complesso di un'applicazione stabile basata sui microservizi è la creazione di una cultura incentrata su contratti solidi e sottoposti al controllo delle versioni. I team di sviluppo devono interiorizzare la comprensione di una modifica che provoca un errore rispetto a una modifica che non provoca un errore. Devono sapere quando è richiesta una nuova release principale. Devono capire come e quando un vecchio contratto può essere ritirato dal servizio. I team devono utilizzare tecniche di comunicazione appropriate, tra cui avvisi di ritiro e disattivazione, per garantire la consapevolezza delle modifiche ai contratti dei microservizi. Anche se può sembrare scoraggiante, integrare queste pratiche nella cultura di sviluppo porterà a grandi miglioramenti in termini di velocità e qualità nel tempo.
Indirizzamento dei microservizi
È possibile indirizzare direttamente i servizi e le versioni del codice. Di conseguenza, puoi eseguire il deployment di nuove versioni del codice affiancate a quelle esistenti e puoi testare il nuovo codice prima di impostarlo come versione di pubblicazione predefinita.
Ogni progetto App Engine ha un servizio predefinito e ogni servizio ha una versione del codice predefinita. Per indirizzare il servizio predefinito della versione predefinita di un progetto,
utilizza il seguente URL:
https://PROJECT_ID.REGION_ID.r.appspot.com
Se esegui il deployment di un servizio denominato user-service, puoi accedere alla versione di pubblicazione predefinita di questo servizio utilizzando il seguente URL:
https://user-service-dot-my-app.REGION_ID.r.appspot.com
Se esegui il deployment di una seconda versione del codice non predefinita denominata banana
nel servizio user-service, puoi accedere direttamente a questa versione del codice
utilizzando il seguente URL:
https://banana-dot-user-service-dot-my-app.REGION_ID.r.appspot.com
Tieni presente che se implementi una seconda versione del codice non predefinita denominata cherry nel servizio default, puoi accedere a questa versione del codice utilizzando il seguente URL:
https://cherry-dot-my-app.REGION_ID.r.appspot.com
App Engine applica la regola secondo cui i nomi delle versioni del codice nel servizio predefinito non possono entrare in conflitto con i nomi dei servizi.
L'indirizzamento diretto di versioni di codice specifiche deve essere utilizzato solo per i test smoke e per facilitare i test A/B, l'avanzamento e il rollback. Il codice cliente deve invece indirizzare solo la versione di pubblicazione predefinita del servizio predefinito o di un servizio specifico:
https://PROJECT_ID.REGION_ID.r.appspot.com
https://SERVICE_ID-dot-PROJECT_ID.REGION_ID.r.appspot.com
Questo stile di indirizzamento consente ai microservizi di eseguire il deployment di nuove versioni dei propri servizi, incluse le correzioni di bug, senza richiedere modifiche ai client.
Utilizzo delle versioni API
Ogni API di microservizio deve avere una versione API principale nell'URL, ad esempio:
/user-service/v1/
Questa versione principale dell'API identifica chiaramente nei log la versione dell'API del microservizio che viene chiamata. Ancora più importante, la versione principale dell'API genera URL diversi, in modo che le nuove versioni principali dell'API possano essere pubblicate affiancate alle vecchie versioni principali dell'API:
/user-service/v1/ /user-service/v2/
Non è necessario includere la versione secondaria dell'API nell'URL perché le versioni secondarie dell'API per definizione non introdurranno modifiche che provocano errori. Infatti, l'inclusione della versione secondaria dell'API nell'URL comporterebbe una proliferazione di URL e causerebbe incertezza sulla capacità di un client di passare a una nuova versione secondaria dell'API.
Tieni presente che questo articolo presuppone un ambiente di integrazione e distribuzione continue in cui il ramo principale viene sempre sottoposto a deployment su App Engine. In questo articolo vengono presentati due concetti distinti di versione:
Versione del codice, che corrisponde direttamente a una versione del servizio App Engine e rappresenta un tag di commit specifico del ramo principale.
Versione dell'API, che corrisponde direttamente a un URL API e rappresenta la forma degli argomenti della richiesta, la forma del documento di risposta e il comportamento dell'API.
Questo articolo presuppone inoltre che un singolo deployment di codice implementerà sia le versioni API precedenti
che quelle nuove di un'API in una versione di codice comune. Ad esempio, il ramo principale
di cui è stato eseguito il deployment potrebbe implementare sia /user-service/v1/ sia
/user-service/v2/. Quando esegui il rollout di nuove versioni secondarie e patch, questo approccio ti consente di dividere il traffico tra due versioni del codice indipendentemente dalle versioni dell'API che il codice implementa effettivamente.
La tua organizzazione può scegliere di sviluppare
/user-service/v1/ e /user-service/v2/
su rami di codice diversi, ovvero nessuna implementazione di codice
implementerà entrambi contemporaneamente. Questo modello è possibile anche su App Engine, ma per dividere il traffico dovresti spostare la versione principale dell'API nel nome del servizio stesso.
Ad esempio, i tuoi clienti utilizzerebbero i seguenti URL:
http://user-service-v1.my-app.REGION_ID.r.appspot.com/user-service/v1/ http://user-service-v2.my-app.REGION_IDappspot.com/user-service/v2/
La versione principale dell'API viene spostata nel nome del servizio stesso, ad esempio
user-service-v1 e user-service-v2.
(Le parti /v1/ e /v2/ del
percorso sono ridondanti in questo modello e
potrebbero essere rimosse, anche se potrebbero comunque essere utili nell'analisi dei log.)
Questo modello richiede un po' più di lavoro perché probabilmente richiede
aggiornamenti agli script di deployment per eseguire il deployment di nuovi servizi in
cambiamenti importanti della versione dell'API. Inoltre, tieni presente il
numero massimo di servizi consentiti
per applicazione App Engine.
Modifiche che provocano errori e modifiche che non provocano errori
È importante comprendere la differenza tra una modifica che causa interruzioni e una modifica che non causa interruzioni. Le modifiche che causano interruzioni sono spesso sottrattive, il che significa che rimuovono una parte del documento di richiesta o risposta. La modifica della forma del documento o del nome delle chiavi può introdurre una modifica che causa interruzioni. I nuovi argomenti obbligatori sono sempre modifiche che causano interruzioni. Le modifiche che causano interruzioni possono verificarsi anche se il comportamento del microservizio cambia.
Le modifiche non distruttive tendono a essere additive. Un nuovo argomento di richiesta facoltativo o una nuova sezione aggiuntiva nel documento di risposta sono modifiche non distruttive. Per ottenere modifiche non distruttive, la scelta della serializzazione on-the-wire è essenziale. Molte serializzazioni sono compatibili con modifiche non distruttive: JSON, buffer di protocollo o Thrift. Quando vengono deserializzate, queste serializzazioni ignorano silenziosamente le informazioni aggiuntive e impreviste. Nei linguaggi dinamici, le informazioni aggiuntive vengono visualizzate semplicemente nell'oggetto deserializzato.
Considera la seguente definizione JSON per il servizio /user-service/v1/:
{
"userId": "UID-123",
"firstName": "Jake",
"lastName": "Cole",
"username": "jcole@example.com"
}
La seguente modifica che provoca un errore richiederebbe una nuova versione del servizio come
/user-service/v2/:
{
"userId": "UID-123",
"name": "Jake Cole", # combined fields
"email": "jcole@example.com" # key change
}
Tuttavia, la seguente modifica non distruttiva non richiede una nuova versione:
{
"userId": "UID-123",
"firstName": "Jake",
"lastName": "Cole",
"username": "jcole@example.com",
"company": "Acme Corp." # new key
}
Deployment di nuove versioni secondarie dell'API non incompatibili
Quando viene eseguito il deployment di una nuova versione secondaria dell'API, App Engine consente di rilasciare la nuova versione del codice
insieme alla versione precedente. Su App Engine,
anche se puoi indirizzare direttamente una qualsiasi delle versioni di cui è stato eseguito il deployment, solo una versione
è la versione di pubblicazione predefinita; ricorda che esiste una versione di pubblicazione predefinita
per ogni servizio. In questo esempio, abbiamo la vecchia versione del codice, denominata apple, che è la versione di pubblicazione predefinita, e implementiamo la nuova versione del codice come versione affiancata, denominata banana. Tieni presente che gli URL dei microservizi
per entrambi sono gli stessi /user-service/v1/ poiché stiamo implementando una
modifica secondaria dell'API non distruttiva.
App Engine fornisce meccanismi per eseguire automaticamente la migrazione del traffico da apple a banana contrassegnando la nuova versione del codice banana come versione di pubblicazione predefinita. Quando viene impostata la nuova versione di pubblicazione predefinita, nessuna nuova richiesta verrà
indirizzata a apple e tutte le nuove richieste verranno indirizzate a banana. In questo modo
esegui il roll forward a una nuova versione del codice che implementa una nuova versione secondaria o patch dell'API
senza alcun impatto sui microservizi client.
In caso di errore, il rollback viene eseguito invertendo la procedura
precedente: imposta di nuovo la versione di pubblicazione predefinita su quella precedente, apple nel nostro
esempio. Tutte le nuove richieste verranno reindirizzate alla vecchia versione del codice e nessuna nuova
richiesta verrà indirizzata a banana. Tieni presente che le richieste in corso possono essere completate.
App Engine offre anche la possibilità di indirizzare solo una determinata percentuale del traffico alla nuova versione del codice. Questa procedura viene spesso chiamata procedura di rilascio canary e il meccanismo è chiamato suddivisione del traffico in App Engine. Puoi indirizzare l'1%, il 10%, il 50% o qualsiasi percentuale di traffico che preferisci verso le nuove versioni del codice e puoi modificare questo importo nel tempo. Ad esempio, potresti implementare la nuova versione del codice in 15 minuti, aumentando lentamente il traffico e monitorando eventuali problemi che potrebbero indicare la necessità di un rollback. Lo stesso meccanismo ti consente di eseguire test A/B su due versioni del codice: imposta la divisione del traffico al 50% e confronta le caratteristiche di rendimento e tasso di errore delle due versioni del codice per confermare i miglioramenti previsti.
L'immagine seguente mostra le impostazioni di suddivisione del traffico nella consoleGoogle Cloud :

Deployment di nuove versioni principali dell'API con modifiche incompatibili
Quando esegui il deployment di versioni principali dell'API che causano interruzioni, il processo di avanzamento e
rollback è lo stesso delle versioni secondarie dell'API che non causano interruzioni. Tuttavia, in genere non esegui alcuna suddivisione del traffico o test A/B perché la versione dell'API che introduce modifiche incompatibili è un URL appena rilasciato, ad esempio /user-service/v2/. Naturalmente, se hai modificato l'implementazione
sottostante della tua vecchia versione principale dell'API, potresti comunque voler utilizzare
la suddivisione del traffico per verificare che la vecchia versione principale dell'API continui a
funzionare come previsto.
Quando esegui il deployment di una nuova versione principale dell'API, è importante ricordare che potrebbero essere ancora in uso anche le versioni principali precedenti dell'API. Ad esempio, /user-service/v1/
potrebbe essere ancora in servizio quando viene rilasciato /user-service/v2/. Questo fatto è una
parte essenziale delle release di codice indipendenti. Puoi disattivare le versioni principali precedenti dell'API solo dopo aver verificato che nessun altro microservizio le richieda, inclusi altri microservizi che potrebbero dover eseguire il rollback a una versione precedente del codice.
Come esempio concreto, immagina di avere un microservizio denominato web-app
che dipende da un altro microservizio denominato user-service. Immagina che
user-service debba modificare un'implementazione sottostante che
renderà impossibile supportare la vecchia versione principale dell'API attualmente utilizzata da web-app, ad esempio comprimendo firstName e lastName
in un unico campo chiamato name. ovvero
user-service deve ritirare una versione principale precedente dell'API.
Per apportare questa modifica, devono essere eseguiti tre deployment separati:
Innanzitutto,
user-servicedeve eseguire il deployment di/user-service/v2/continuando a supportare/user-service/v1/. Questo deployment potrebbe richiedere la scrittura di codice temporaneo per supportare la compatibilità con le versioni precedenti, una conseguenza comune nelle applicazioni basate su microserviziSuccessivamente,
web-appdeve eseguire il deployment del codice aggiornato che modifica la sua dipendenza da/user-service/v1/a/user-service/v2/Infine, dopo che il team
user-serviceha verificato cheweb-appnon richiede più/user-service/v1/e cheweb-appnon deve eseguire il rollback, il team può implementare il codice che rimuove il vecchio endpoint/user-service/v1/e qualsiasi codice temporaneo necessario per supportarlo.
Sebbene tutta questa attività possa sembrare onerosa, è un processo essenziale nelle applicazioni basate su microservizi ed è proprio il processo che consente cicli di rilascio di sviluppo indipendenti. Per essere chiari, questo processo sembra essere piuttosto dipendente, ma è importante sottolineare che ogni passaggio precedente può verificarsi in sequenze temporali indipendenti e che l'avanzamento e il rollback avvengono nell'ambito di un singolo microservizio. Solo l'ordine dei passaggi è fisso e i passaggi potrebbero svolgersi nell'arco di molte ore, giorni o persino settimane.
Passaggi successivi
- Scopri una panoramica dell'architettura dei microservizi su App Engine.
- Scopri come creare e denominare ambienti di sviluppo, test, controllo qualità, gestione temporanea e di produzione con microservizi in App Engine.
- Scopri le best practice per le prestazioni dei microservizi.
- Scopri come eseguire la migrazione di un'applicazione monolitica esistente a una con microservizi.