Contratti, indirizzamento e API per i microservizi

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 il giorno Febbraio 2020, REGION_ID.r è incluso in 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 è 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 un contratto precedente, quindi è importante tenerne conto nel norme sul ritiro e la disattivazione.

Una cultura incentrata su contratti solidi e sottoposti al controllo delle versioni è probabilmente l'approccio più complesso aspetto organizzativo di un'applicazione stabile basata su microservizi. I team di sviluppo devono comprendere la differenza tra una modifica che provoca un errore e una modifica non dannosa. 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. Anche se può sembrare scoraggiante, l'adozione di queste pratiche nella 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 nuove versioni del codice affiancate con quelle esistenti ed è possibile testare prima di renderla la versione di servizio predefinita.

Ogni progetto App Engine ha un servizio predefinito e ogni servizio ha un codice predefinito. completamente gestita. 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 del codice non predefinita denominata banana al servizio user-service, puoi accedere direttamente alla versione del 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 stabilisce che i nomi delle versioni del codice non è in conflitto con i nomi dei servizi.

Versioni del codice specifiche con indirizzo diretto devono essere utilizzate solo per i fumatori test e facilitare i test A/B, in sequenza e 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 propri servizi, incluse le correzioni di bug, senza richiedere modifiche ai client.

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 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é, per definizione, le versioni secondarie dell'API non introducono modifiche che causano interruzioni. Infatti, l'inclusione della versione secondaria dell'API nell'URL provocherebbe una proliferazione di e creano incertezza sulla capacità di un cliente di passare a un nuovo minorenne Versione API.

Tieni presente che questo articolo presuppone un ambiente di integrazione e distribuzione continue in cui viene sempre eseguito il deployment del ramo principale 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 è inoltre possibile su App Engine, ma 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 agli script di deployment per eseguire il deployment di nuovi servizi modifiche principali alla versione API. Inoltre, tieni presente numero massimo di servizi consentiti per ogni 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. rompere i cambiamenti sono spesso sottrattivi, nel senso che parte del documento di richiesta o di risposta. La modifica della forma del documento o del nome delle chiavi può comportare una modifica che comporta l'interruzione del servizio. Nuovi gli argomenti richiesti interrompono sempre le modifiche. Possono verificarsi anche modifiche che provocano un errore se cambia il comportamento del microservizio.

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 facili modifiche complete: JSON, buffer di protocollo o Thrift. Quando vengono deserializzate, queste serializzazioni ignorano silenziosamente informazioni aggiuntive e impreviste. Nella lingue dinamiche, le informazioni aggiuntive appaiono semplicemente nel .

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. In App Engine, sebbene sia possibile gestire direttamente qualsiasi versione 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 eseguendo il deployment di 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. Se viene impostata la nuova versione di pubblicazione predefinita, non verranno effettuate nuove richieste indirizzato 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 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 dell'API con modifiche non compatibili

Quando esegui il deployment delle principali versioni API, il processo di implementazione il rollback è lo stesso delle versioni secondarie dell'API senza interruzioni. Tuttavia, di solito non esegue alcuna suddivisione del traffico o test A/B perché Per versione API si intende un URL appena rilasciato, come /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 è un elemento 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 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 può richiedere la scritta per supportare la compatibilità con le versioni precedenti, una conseguenza comune di applicazioni basate su microservizi

  • Successivamente, 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 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 questa attività possa sembrare onerosa, è un processo essenziale nella basate su microservizi ed è esattamente il processo che consente indipendenti cicli di rilascio per lo sviluppo. Per essere chiari, questo processo sembra essere abbastanza dipendente, ma è importante sottolineare che ogni passaggio riportato sopra può avvenire su tempistiche indipendenti e che l'avanzamento e il rollback avvengono nell'ambito di un singolo microservice. È fisso solo l'ordine dei passaggi, che possono essere avvengono nell'arco di molte ore, giorni o persino settimane.

Passaggi successivi