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.
Lo sviluppo software si basa su compromessi e i microservizi non fanno eccezione. Ciò che guadagni in termini di indipendenza di deployment e funzionamento del codice, lo paghi in termini di overhead delle prestazioni. Questa sezione fornisce alcuni consigli sui passaggi che puoi seguire per ridurre al minimo questo impatto.
Trasformare le operazioni CRUD in microservizi
I microservizi sono particolarmente adatti alle entità a cui si accede con il pattern create, retrieve, update, delete (CRUD). Quando lavori con queste entità, in genere utilizzi una sola entità alla volta, ad esempio un utente, ed esegui una sola azione CRUD alla volta. Pertanto, per l'operazione è necessaria una sola chiamata al microservizio. Cerca entità che abbiano operazioni CRUD più un insieme di metodi aziendali che potrebbero essere utilizzati in molte parti dell'applicazione. Queste entità sono ottimi candidati per i microservizi.
Fornire API batch
Oltre alle API in stile CRUD, puoi comunque fornire buone prestazioni dei microservizi per gruppi di entità fornendo API batch. Ad esempio, anziché esporre solo un metodo API GET che recupera un singolo utente, fornisci un'API che accetta un insieme di ID utente e restituisce un dizionario degli utenti corrispondenti:
Richiesta:
/user-service/v1/?userId=ABC123&userId=DEF456&userId=GHI789Risposta:
{
"ABC123": {
"userId": "ABC123",
"firstName": "Jake",
… },
"DEF456": {
"userId": "DEF456",
"firstName": "Sue",
… },
"GHI789": {
"userId": "GHI789",
"firstName": "Ted",
… }
}
L'SDK App Engine supporta molte API batch, ad esempio la possibilità di recuperare molte entità da Cloud Datastore tramite una singola RPC, pertanto la gestione di questi tipi di API batch può essere molto efficiente.
Utilizzare richieste asincrone
Spesso, devi interagire con molti microservizi per comporre una risposta.
Ad esempio, potresti dover recuperare le preferenze dell'utente che ha eseguito l'accesso e
i dettagli della sua azienda. Spesso, queste informazioni non dipendono l'una dall'altra e puoi recuperarle in parallelo. La libreria Urlfetch nell'SDK App Engine supporta le richieste asincrone, consentendoti di chiamare i microservizi in parallelo.
from google.appengine.api import urlfetch
preferences_rpc = urlfetch.create_rpc()
urlfetch.make_fetch_call(preferences_rpc,
'https://preferences-service-dot-my-app.uc.r.appspot.com/preferences-service/v1/?userId=ABC123')
company_rpc = urlfetch.create_rpc()
urlfetch.make_fetch_call(company_rpc,
'https://company-service-dot-my-app.uc.r.appspot.com/company-service/v3/?companyId=ACME')
### microservice requests are now occurring in parallel
try:
preferences_response = preferences_rpc.get_result() # blocks until response
if preferences_response.status_code == 200:
# deserialize JSON, or whatever is appropriate
else:
# handle error
except urlfetch.DownloadError:
# timeout, or other transient error
try:
company_response = company_rpc.get_result() # blocks until response
if company_response.status_code == 200:
# deserialize JSON, or whatever is appropriate
else:
# handle error
except urlfetch.DownloadError:
# timeout, or other transient error
Lavorare in parallelo spesso va contro una buona struttura del codice perché, in uno scenario reale, spesso utilizzi una classe per incapsulare i metodi delle preferenze e un'altra classe per incapsulare i metodi aziendali. È difficile sfruttare
le chiamate asincrone Urlfetch senza interrompere questo incapsulamento. Una buona
soluzione esiste nel pacchetto NDB dell'SDK Python di App Engine: i
tasklet.
I tasklet ti consentono di mantenere una buona incapsulamento nel codice, offrendo comunque
un meccanismo per eseguire chiamate parallele ai microservizi. Tieni presente che i tasklet utilizzano
futures anziché RPC, ma l'idea è simile.
Utilizzare il percorso più breve
A seconda di come richiami Urlfetch, puoi fare in modo che vengano utilizzate infrastrutture
e route diverse. Per utilizzare il percorso con il rendimento migliore, tieni presente i
seguenti consigli:
- Utilizza
REGION_ID.r.appspot.com, non un dominio personalizzato - Un dominio personalizzato fa sì che venga utilizzato un percorso diverso durante il routing tramite l'infrastruttura di Google. Poiché le chiamate ai microservizi sono interne, è facile
da eseguire e funziona meglio se utilizzi
https://PROJECT_ID.REGION_ID.r.appspot.com. - Imposta
follow_redirectssuFalse - Imposta esplicitamente
follow_redirects=Falsequando chiamiUrlfetch, in quanto evita un servizio più pesante progettato per seguire i reindirizzamenti. I tuoi endpoint API non devono reindirizzare i client, perché sono i tuoi microservizi e gli endpoint devono restituire solo risposte HTTP delle serie 200, 400 e 500. - Preferisci i servizi all'interno di un progetto rispetto a più progetti
- Esistono validi motivi per utilizzare più progetti durante la creazione di un'applicazione basata su microservizi, ma se il rendimento è il tuo obiettivo principale, utilizza i servizi all'interno di un singolo progetto. I servizi di un progetto sono ospitati nello stesso data center e, anche se il throughput sulla rete inter-data center di Google è eccellente, le chiamate locali sono più veloci.
Evitare chiacchiere durante l'applicazione della sicurezza
È dannoso per le prestazioni utilizzare meccanismi di sicurezza che comportano molte comunicazioni di andata e ritorno per autenticare l'API chiamante. Ad esempio, se il tuo microservizio deve convalidare un ticket della tua applicazione richiamando l'applicazione, hai effettuato una serie di round trip per ottenere i dati.
Un'implementazione di OAuth2 può ammortizzare questo costo nel tempo utilizzando i token di aggiornamento e memorizzando nella cache un token di accesso tra le chiamate Urlfetch. Tuttavia, se
il token di accesso memorizzato nella cache è archiviato in memcache, dovrai sostenere l'overhead
di memcache per recuperarlo. Per evitare questo sovraccarico, puoi memorizzare nella cache il token di accesso
nella memoria dell'istanza, ma l'attività OAuth2
si verificherà comunque di frequente, poiché ogni nuova istanza negozia un token di accesso. Ricorda che le istanze App
Engine vengono avviate e arrestate di frequente. Una combinazione di memcache e cache dell'istanza contribuirà a mitigare il problema, ma la soluzione inizierà a diventare più complessa.
Un altro approccio che funziona bene è condividere un token segreto tra i microservizi, ad esempio trasmesso come intestazione HTTP personalizzata. In questo approccio, ogni microservizio potrebbe avere un token univoco per ogni chiamante. In genere, i segreti condivisi sono una scelta discutibile per le implementazioni di sicurezza, ma poiché tutti i microservizi si trovano nella stessa applicazione, il problema è meno grave, visti i miglioramenti delle prestazioni. Con un secret condiviso, il microservizio deve solo eseguire un confronto tra stringhe del secret in entrata e un dizionario presumibilmente in memoria e l'applicazione della sicurezza è molto leggera.
Se tutti i tuoi microservizi si trovano su App Engine, puoi anche esaminare l'intestazione
X-Appengine-Inbound-Appid in entrata.
Questa intestazione viene aggiunta dall'infrastruttura Urlfetch quando viene effettuata una richiesta a
un altro progetto App Engine e non può essere impostata da una parte esterna. A seconda
del requisito di sicurezza, i microservizi potrebbero ispezionare questo header in entrata
per applicare la policy di sicurezza.
Trace le richieste di microservizi
Man mano che crei l'applicazione basata su microservizi, inizi ad accumulare
overhead dalle chiamate Urlfetch successive. In questi casi, puoi utilizzare
Cloud Trace
per capire quali chiamate vengono
effettuate e dove si trova l'overhead. È importante sottolineare che Cloud Trace può anche aiutarti a identificare
i punti in cui vengono richiamati microservizi indipendenti in serie, in modo da poter
refactoring del codice per eseguire questi recuperi in parallelo.
Una funzionalità utile di Cloud Trace si attiva quando utilizzi più servizi all'interno di un singolo progetto. Man mano che vengono effettuate chiamate tra i servizi di microservizi nel tuo progetto, Cloud Trace comprime tutte le chiamate in un unico grafico delle chiamate per consentirti di visualizzare l'intera richiesta end-to-end come una singola traccia.

Tieni presente che nell'esempio precedente le chiamate a pref-service e
user-service vengono eseguite in parallelo utilizzando un Urlfetch asincrono,
quindi gli RPC appaiono in ordine casuale nella visualizzazione.
Tuttavia, si tratta comunque di uno strumento prezioso per diagnosticare la latenza.
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 la progettazione di API per la comunicazione tra microservizi.
- Scopri come eseguire la migrazione di un'applicazione monolitica esistente a una con microservizi.