Contratti, indirizzamento e API per i microservizi

ID regione

REGION_ID è un codice abbreviato assegnato da Google in base alla regione selezionata al momento della creazione dell'app. Il codice non corrispondono a un paese o a una provincia, anche se potrebbero essere visualizzati alcuni ID regione in modo simile ai codici paese e provincia 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.

I microservizi su App Engine in genere si chiamano reciprocamente utilizzando il servizio RESTful basato su HTTP su quelle di livello inferiore. È anche possibile richiamare i microservizi in background utilizzando Si applicano le code di attività e 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 nessuna un altro microservizio si basa su un particolare contratto sottoposto al controllo delle versioni. 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. Sviluppo i team devono interiorizzare la comprensione di un cambiamento che provoca un cambiamento piuttosto che un cambiamento costante. Devono sapere quando è richiesta una nuova release principale. Devono capire come e quando un vecchio contratto può essere ritirato. I team devono impiegare tecniche di comunicazione appropriate, incluso il ritiro e avvisi di disattivazione, per garantire la consapevolezza delle modifiche al microservizio contratti. Per quanto possa sembrare scoraggiante, integrare queste pratiche in la cultura dello 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 delle nuove versioni di 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 di codice predefinita. Per gestire 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 pubblicazione predefinita del servizio tramite 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 del codice non predefinita denominata cherry nel default, puoi accedere alla versione del 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 gestire solo i valori predefiniti di servizio 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 loro servizi, incluse correzioni di bug, senza richiedere alcuna modifica ai clienti.

Utilizzo delle versioni 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 viene chiamato. Ma soprattutto, la versione principale dell'API produce diversi URL, in modo che le nuove versioni principali delle API possano essere pubblicate affiancate versioni principali dell'API precedente:

/user-service/v1/
/user-service/v2/

Non è necessario includere nell'URL la versione secondaria dell'API perché l'API secondaria per definizione non introdurranno modifiche che provocano un errore. 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 API, che è mappato direttamente all'URL di un'API e rappresenta la forma gli argomenti della richiesta, la forma del documento di risposta, e il comportamento dell'API.

Questo articolo presuppone anche che il deployment di un singolo codice implementerà sia i vecchi e 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 minori 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; vale a dire che nessun deployment di codice di implementarle entrambe 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 potrebbero utilizzare 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/, /v2/ del sono ridondanti in questo modello potrebbe essere rimosso, anche se possono comunque 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 e non interrompono

È importante comprendere la differenza tra una modifica che comporta una interruzione e una modifica non che comporta una interruzione. rompere i cambiamenti sono spesso sottrattivi, nel senso che parte del documento di richiesta o di risposta. Modificando la forma del documento o la modifica del nome delle chiavi può introdurre una modifica che provoca un errore. I nuovi argomenti obbligatori sono sempre modifiche che comportano interruzioni. Le modifiche incompatibili possono verificarsi anche se il comportamento del microservizio cambia.

I cambiamenti continui tendono ad essere cumulativi. È disponibile una nuova un argomento di richiesta o una nuova sezione aggiuntiva nel documento di risposta modifiche continue. Al fine di ottenere cambiamenti costanti, la scelta la serializzazione on-the-wire è essenziale. 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. Nota che il microservizio Gli URL di entrambi sono gli stessi /user-service/v1/ poiché stiamo implementando modifica minima dell'API.

App Engine fornisce meccanismi per eseguire automaticamente la migrazione del traffico da apple a banana contrassegnando la nuova versione del codice banana come pubblicazione predefinita completamente gestita. 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. Ecco come esegui il rollback a una nuova versione del codice che implementa una nuova API secondaria o patch senza alcun impatto sui microservizi client.

In caso di errore, il rollback si ottiene invertendo quanto riportato sopra processo: reimposta la versione di pubblicazione predefinita su quella precedente, apple nel 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 in 15 minuti, aumentando lentamente il traffico e verificando eventuali problemi che potrebbero far emergere un rollback obbligatorio. 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:

Impostazioni di suddivisione del traffico nella console Google Cloud

Deployment di nuove versioni principali delle API

Quando esegui il deployment delle principali versioni API, il processo di implementazione il rollback è lo stesso delle versioni secondarie dell'API senza interruzioni. 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/. Ovviamente, 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 è parte essenziale delle release di codice indipendenti. Puoi solo respingere il vecchio corso di studi versioni API dopo aver verificato che nessun altro microservizio le richiede, inclusi altri microservizi che potrebbero dover eseguire il rollback a un codice precedente completamente gestita.

Come esempio concreto, immagina di avere un microservizio chiamato web-app, che dipende da un altro microservizio, denominato user-service. Immagina user-service deve modificare alcune implementazioni sottostanti che impossibile supportare la vecchia versione principale dell'API web-app sta attualmente utilizzando, ad esempio la compressione di firstName e lastName in un unico campo denominato name. Vale a dire che user-service deve disattivare una versione principale precedente dell'API.

Per apportare questa modifica, è necessario eseguire tre deployment separati:

  • 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 microservizi

  • Successivamente, web-app deve eseguire il deployment del codice aggiornato che modifica la sua dipendenza da Da /user-service/v1/ a /user-service/v2/

  • Infine, dopo che il team di user-service ha verificato che web-app non richiede più /user-service/v1/ e che web-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. Precisiamo che questo processo appare molto dipendente, ma è importante sottolineare che ogni passaggio precedente può avvenire su le tempistiche, il rollback e il rollback avvengono nell'ambito di una microservizio. È fisso solo l'ordine dei passaggi, che possono essere avvengono nell'arco di molte ore, giorni o persino settimane.

Passaggi successivi