ID regione
REGION_ID
è un codice abbreviato assegnato da Google 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 di App Engine. Per le app esistenti create prima di questa data, l'ID regione è facoltativo nell'URL.
Scopri di più sugli ID regione.
In genere, i microservizi su App Engine si richiamano a vicenda utilizzando API RESTful basate su HTTP. È anche possibile invocare 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 assicurarti che l'applicazione basata su microservizi sia stabile, sicura e abbia un buon rendimento.
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 ottenere questa indipendenza, ciascun microservizio deve fornire un contratto ben definito e sottoposto 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 questi 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 comprendere la differenza tra una modifica che provoca un errore e una modifica non dannosa. Devono sapere quando è necessaria una nuova release principale. Devono capire come e quando un vecchio contratto può essere ritirato. I team devono utilizzare tecniche di comunicazione appropriate, tra cui comunicazioni relative al ritiro e al ritiro, per garantire la consapevolezza delle modifiche ai contratti dei microservizi. Anche se può sembrare scoraggiante, l'adozione di queste pratiche nella tua cultura di sviluppo produrrà grandi miglioramenti in termini di velocità e qualità nel tempo.
Indirizzare i microservizi
I servizi e le versioni del codice possono essere indirizzati direttamente. Di conseguenza, puoi eseguire il deployment di nuove versioni di codice affiancate a quelle esistenti e 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 di codice predefinita. Per accedere al 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 servizio predefinita utilizzando il seguente URL:
https://user-service-dot-my-app.REGION_ID.r.appspot.com
Se esegui il deployment di una seconda versione di codice non predefinita denominata banana
nel servizio user-service
, puoi accedere direttamente a questa versione di codice
utilizzando il seguente URL:
https://banana-dot-user-service-dot-my-app.REGION_ID.r.appspot.com
Tieni presente che se esegui il deployment di una seconda versione di codice non predefinita denominata cherry
nel servizio default
, puoi accedere a questa versione di codice utilizzando il seguente URL:
https://cherry-dot-my-app.REGION_ID.r.appspot.com
App Engine applica la regola che i nomi delle versioni di 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 di fumosità e per facilitare i test A/B, l'applicazione e il rollback. Il codice client deve invece indirizzare solo la versione predefinita in esecuzione 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 dell'API
Ogni API di microservizio deve avere una versione principale dell'API 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 insieme alle vecchie versioni principali dell'API:
/user-service/v1/ /user-service/v2/
Non è necessario includere la versione secondaria dell'API nell'URL perché, per definizione, le versioni secondarie dell'API non introducono modifiche che causano interruzioni. 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 continua in cui il ramo principale viene sempre eseguito in App Engine. In questo articolo sono presenti due concetti distinti di versione:
Versione codice, che si mappa direttamente a una versione del servizio App Engine e rappresenta un determinato tag commit del ramo principale.
Versione dell'API, che si mappa direttamente a un URL dell'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 del codice implementi sia le vecchie che le nuove versioni 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 implementi nuove versioni secondarie e patch, questo approccio ti consente di suddividere il traffico tra due versioni di codice indipendentemente dalle versioni dell'API effettivamente implementate dal codice.
La tua organizzazione può scegliere di sviluppare /user-service/v1/
e /user-service/v2/
su rami di codice diversi, ovvero nessun deployment di codice implementerà entrambi contemporaneamente. Questo modello è possibile anche su App Engine, ma per suddividere il traffico devi spostare la versione principale dell'API nel nome del servizio stesso.
Ad esempio, i tuoi clienti utilizzeranno 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 inserita 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 essere utili nell'analisi dei log.
Questo modello richiede un po' più di lavoro perché probabilmente richiede aggiornamenti agli script di deployment per il deployment di nuovi servizi in caso di modifiche sostanziali alle versioni dell'API. Inoltre, tieni presente il
numero massimo di servizi consentiti
per applicazione App Engine.
Modifiche che provocano un errore e modifiche non che provocano un errore
È importante comprendere la differenza tra una modifica che comporta una interruzione e una modifica non che comporta una interruzione. Le modifiche incompatibili sono spesso di tipo sottrattivo, ovvero rimuovono parte del documento di richiesta o risposta. La modifica della forma del documento o del nome delle chiavi può comportare una modifica che comporta l'interruzione del servizio. I nuovi argomenti obbligatori sono sempre modifiche che comportano interruzioni. Le modifiche incompatibili possono verificarsi anche se il comportamento del microservizio cambia.
Le modifiche non invasive tendono ad essere additive. Un nuovo argomento facoltativo della richiesta o una nuova sezione aggiuntiva nel documento di risposta sono modifiche non invasive. Per apportare modifiche non invasive, è essenziale scegliere la serializzazione on-the-wire. Molte serializzazioni sono compatibili con le modifiche non invasive: JSON, Protocol Buffers o Thrift. Quando vengono deserializzate, queste serializzazioni ignorano silenziosamente informazioni aggiuntive e impreviste. Nelle lingue dinamiche, le informazioni aggiuntive vengono visualizzate semplicemente nell'oggetto deserializzato.
Prendi in considerazione 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 richiede la ridefinizione della 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 invasiva non richiede una nuova versione:
{
"userId": "UID-123",
"firstName": "Jake",
"lastName": "Cole",
"username": "jcole@example.com",
"company": "Acme Corp." # new key
}
Eseguire il deployment di nuove versioni minori dell'API non incompatibili
Quando esegui il deployment di una nuova versione minore 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 delle versioni di cui è stato eseguito il deployment, solo una è 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 minore non invasiva dell'API.
App Engine fornisce meccanismi per eseguire la migrazione automatica del traffico da apple
a banana
contrassegnando la nuova versione di 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, puoi eseguire il passaggio a una nuova versione di codice che implementa una nuova versione dell'API secondaria o di patch senza alcun impatto sui microservizi client.
In caso di errore, il rollback viene eseguito invertendo la procedura precedente: reimposta 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à reindirizzata a banana
. Tieni presente che le richieste in corso possono essere completate.
App Engine offre anche la possibilità di indirizzare solo una determinata percentuale di traffico alla nuova versione del codice. Questa procedura è 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 alle nuove versioni del codice e puoi modificare questo importo nel tempo. Ad esempio, puoi implementare la nuova versione del codice nell'arco di 15 minuti, aumentando lentamente il traffico e controllando la presenza di eventuali problemi che potrebbero indicare la necessità di un rollback. Lo stesso meccanismo ti consente di eseguire test A/B su due versioni di codice: imposta la suddivisione del traffico al 50% e confronta le caratteristiche di rendimento e di tasso di errore delle due versioni di codice per confermare i miglioramenti previsti.
L'immagine seguente mostra le impostazioni di suddivisione del traffico nella console Google Cloud:
Deployment di nuove versioni principali dell'API con modifiche non compatibili
Quando esegui il deployment di versioni principali dell'API che non sono compatibili con le versioni precedenti, la procedura di applicazione e di rollback è la stessa delle versioni secondarie dell'API compatibili con le versioni precedenti. Tuttavia, solitamente non esegui suddivisioni del traffico o test A/B perché la versione dell'API che causa interruzioni è un URL appena rilasciato, ad esempio/user-service/v2/
. Naturalmente, se hai modificato l'implementazione di base della vecchia versione principale dell'API, ti consigliamo di utilizzare comunque 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 esecuzione anche le vecchie versioni principali dell'API. Ad esempio, /user-service/v1/
potrebbe essere ancora pubblicato quando viene rilasciato /user-service/v2/
. Questo fatto è un elemento essenziale delle release di codice indipendenti. Potresti disattivare le vecchie versioni principali
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 di base che
renderà impossibile supportare la vecchia versione principale dell'API attualmente in uso da web-app
, ad esempio l'unione di firstName
e lastName
in un unico campo denominato name
. In altre parole,user-service
deve disattivare una vecchia versione principale dell'API.
Per apportare questa modifica, è necessario eseguire tre implementazioni distinte:
Innanzitutto,
user-service
deve 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-app
deve eseguire il deployment del codice aggiornato che modifica la dipendenza da/user-service/v1/
a/user-service/v2/
Infine, dopo che il team di
user-service
ha verificato cheweb-app
non richiede più/user-service/v1/
e cheweb-app
non necessita di un rollback, il team può eseguire il deployment del 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 i cicli di rilascio dello sviluppo indipendente. Per essere chiari, questo processo sembra essere abbastanza dipendente, ma è importante sottolineare che ogni passaggio riportato sopra può avvenire su tempistiche indipendenti e l'avanzamento e il rollback avvengono nell'ambito di un singolo microservice. Solo l'ordine dei passaggi è fisso e i passaggi possono essere svolti nell'arco di molte ore, giorni o addirittura settimane.
Passaggi successivi
- Consulta una panoramica dell'architettura dei microservizi su App Engine.
- Scopri come creare e assegnare un nome agli ambienti di sviluppo, test, QA, gestione temporanea e di produzione con microservizi in App Engine.
- Scopri le best practice per il rendimento dei microservizi.
- Scopri come eseguire la migrazione di un'applicazione monolitica esistente a un'applicazione con microservizi.