In che modo le architetture di sistema dei microservizi evitano i colli di bottiglia della rete?


72

Ho letto molto sulle architetture di microservizi per le applicazioni server e mi chiedevo come l'utilizzo della rete interna non costituisse un collo di bottiglia o uno svantaggio significativo rispetto a un'architettura monolitica.

Per motivi di precisione, ecco le mie interpretazioni dei due termini:

  1. Architettura monolite: un'applicazione in una sola lingua che gestisce tutte le funzionalità, i dati, ecc. Un bilanciamento del carico distribuisce le richieste dell'utente finale su più macchine, ognuna delle quali esegue un'istanza della nostra applicazione.

  2. Architettura dei microservizi: molte applicazioni (microservizi) che gestiscono una piccola parte della funzionalità e dei dati. Ogni microservizio espone un'API comune a cui si accede attraverso la rete (al contrario della comunicazione tra processi o della memoria condivisa sullo stesso computer). Le chiamate API vengono ricucite principalmente sul server per produrre una pagina, anche se forse parte di questo lavoro viene svolto dal client che interroga i singoli microservizi.

Secondo la mia ingenua immaginazione, sembra che un'architettura di microservizi utilizzi un traffico di rete lento anziché risorse più veloci sulla stessa macchina (la memoria e il disco). In che modo si garantisce che le query API attraverso la rete interna non rallentino il tempo di risposta complessivo?


La rete interna è spesso di 1 Gbps, a volte più veloce. Pensa alla dimensione media della risposta JSON da un'API. Quante di queste risposte possono essere trasmesse su una connessione da 1 Gbps in un secondo?
Arseni Mourzenko,

3
se pensi di aver bisogno di microservizi - e potresti! - due libri eccellenti da preparare: amazon.com/Building-Microservices-Sam-Newman/dp/1491950358 e amazon.com/Release-It-Production-Ready-Pragmatic-Programmers/dp/…
Steven A. Lowe

@MainMa il problema non è nella larghezza di banda, ma in ritardo. E se hai bisogno di andata e ritorno, rimarrai sorpreso dalla scarsa larghezza di banda che puoi utilizzare
Stephan Eggermont,

Risposte:


61

Le reti interne utilizzano spesso connessioni a 1 Gbps o più veloci. Le connessioni in fibra ottica o il collegamento consentono larghezze di banda molto più elevate tra i server. Ora immagina la dimensione media di una risposta JSON da un'API. Quante di queste risposte possono essere trasmesse su una connessione da 1 Gbps in un secondo?

Facciamo davvero la matematica. 1 Gbps è 131 072 KB al secondo. Se una risposta JSON media è di 5 KB (il che è abbastanza!), Puoi inviare 26 214 risposte al secondo attraverso il filo con solo una coppia di macchine . Non male, vero?

Questo è il motivo per cui la connessione di rete di solito non è il collo di bottiglia.

Un altro aspetto dei microservizi è che puoi ridimensionare facilmente. Immagina due server, uno che ospita l'API, un altro che la consuma. Se mai la connessione diventa il collo di bottiglia, aggiungi solo altri due server e puoi raddoppiare le prestazioni.

Questo è quando le nostre precedenti 26 214 risposte al secondo diventano troppo piccole per la scala dell'app. Aggiungete altre nove coppie e ora siete in grado di servire 262 140 risposte.

Ma torniamo alla nostra coppia di server e facciamo alcuni confronti.

  • Se una query media non memorizzata nella cache in un database impiega 10 ms., Hai un limite di 100 query al secondo. 100 query. 26 214 risposte. Raggiungere la velocità di 26 214 risposte al secondo richiede una grande quantità di memorizzazione nella cache e ottimizzazione (se la risposta deve effettivamente fare qualcosa di utile, come interrogare un database; le risposte in stile "Hello World" non si qualificano).

  • Sul mio computer, in questo momento, DOMContentLoaded per la home page di Google è successo 394 ms. dopo l'invio della richiesta. Sono meno di 3 richieste al secondo. Per la home page di Programmers.SE, è successo 603 ms. dopo l'invio della richiesta. Non sono nemmeno 2 richieste al secondo. A proposito, ho una connessione Internet a 100 Mbps e un computer veloce: molti utenti aspetteranno più a lungo.

    Se il collo di bottiglia è la velocità di rete tra i server, quei due siti potrebbero letteralmente fare migliaia di chiamate a diverse API mentre servono la pagina.

Questi due casi mostrano che la rete probabilmente non sarà il tuo collo di bottiglia in teoria (in pratica, dovresti fare i benchmark effettivi e la profilazione per determinare la posizione esatta del collo di bottiglia del tuo particolare sistema ospitato su un particolare hardware). Il tempo impiegato per svolgere il lavoro effettivo (che si tratti di query SQL, compressione o altro) e di inviare il risultato all'utente finale è molto più importante.

Pensa ai database

Di solito, i database sono ospitati separatamente dall'applicazione Web che li utilizza. Ciò può destare preoccupazione: che dire della velocità di connessione tra il server che ospita l'applicazione e il server che ospita il database?

Sembra che ci siano casi in cui, in effetti, la velocità di connessione diventa problematica, cioè quando si archiviano enormi quantità di dati che non devono essere elaborati dal database stesso e dovrebbero essere disponibili in questo momento (ovvero file binari di grandi dimensioni). Ma tali situazioni sono rare: nella maggior parte dei casi, la velocità di trasferimento non è così grande rispetto alla velocità di elaborazione della query stessa.

Quando la velocità di trasferimento in realtà è importante quando un'azienda sta ospitando grandi set di dati su un NAS e al NAS si accede da più client contemporaneamente. Qui è dove una SAN può essere una soluzione. Detto questo, questa non è l'unica soluzione. I cavi Cat 6 possono supportare velocità fino a 10 Gbps; l'incollaggio può anche essere usato per aumentare la velocità senza cambiare i cavi o gli adattatori di rete. Esistono altre soluzioni che prevedono la replica dei dati su più NAS.

Dimentica la velocità; pensa alla scalabilità

Un punto importante di un'app Web è la possibilità di ridimensionare. Mentre le prestazioni effettive contano (perché nessuno vuole pagare per server più potenti), la scalabilità è molto più importante, perché ti consente di gettare hardware aggiuntivo quando necessario.

  • Se disponi di un'app non particolarmente veloce, perderai denaro perché avrai bisogno di server più potenti.

  • Se disponi di un'app veloce che non può essere ridimensionata, perderai clienti perché non sarai in grado di rispondere a una domanda crescente.

Allo stesso modo, dieci anni fa le macchine virtuali erano percepite come un enorme problema di prestazioni. In effetti, l'hosting di un'applicazione su un server anziché l'hosting su una macchina virtuale ha avuto un impatto importante sulle prestazioni. Mentre il divario è molto più piccolo oggi, esiste ancora.

Nonostante questa perdita di prestazioni, gli ambienti virtuali sono diventati molto popolari a causa della flessibilità che offrono.

Come con la velocità della rete, potresti scoprire che la VM è il vero collo di bottiglia e, data la tua scala effettiva, risparmierai miliardi di dollari ospitando la tua app direttamente, senza le VM. Ma questo non è ciò che accade per il 99,9% delle app: il loro collo di bottiglia è da qualche altra parte e l'inconveniente di una perdita di alcuni microsecondi a causa della VM è facilmente compensato dai benefici dell'astrazione e della scalabilità dell'hardware.


Certo, possiamo dire che le risposte JSON sono piccole, ma per quanto riguarda la loro quantità ? Sento che un sito Web sotto carico pesante avrebbe più traffico di rete in un'architettura a microservizi rispetto a un'architettura monolitica (dove l'unico traffico di rete è da / verso i server di database). La memorizzazione nella cache può essere d'aiuto, ma per il contenuto in tempo reale e / o generato dinamicamente, non so fino a che punto andrebbe la cache.
James Mishra,

@JamesMishra: ho modificato la mia risposta per rispondere alle tue preoccupazioni.
Arseni Mourzenko

La tua risposta è perfetta . Non solo hai risposto a tutte le obiezioni a cui riesco a pensare, hai anche risposto a obiezioni a cui non avevo pensato.
James Mishra,

5
I miei 2 centesimi dal mondo reale: un sistema composto da microservizi molto loquaci può subire problemi di prestazioni a causa di una rete soffocata. In questi casi, la cache e un design basato su Stream di eventi sono tuoi amici. Oltre alla rete, alla CPU e alla memoria, un sistema basato su microservizi deve anche incorporare la resilienza nel suo design: cosa succede se un microservizio è inattivo? Come si creano tentativi, transazioni distribuite, autorigenerazione, monitoraggio - Suggerisco di cercare "devi essere così alto per usare i microservizi"
Sudhanshu Mishra,

4
Per favore, correggimi se sbaglio, ma per quanto ne so, se hai una rete da 1 Gbps, significa che puoi teoricamente inviare dati da 1 Gb al secondo attraverso quella rete. Indipendentemente dal numero di connessioni. Maggiore è il numero di connessioni, minore è la larghezza di banda per ciascuna connessione. Quindi, il tuo limite effettivo senza aggiornare la tua rete per supportare una larghezza di banda maggiore sarebbe 26.214 risposte al secondo. L'aggiunta di più server non aumenterà la larghezza di banda della rete. Se un singolo cluster può sputare quella quantità di traffico, l'aggiunta di più server che generano ancora più dati congestionerà la tua rete.
Sebbe,

7

Penso che stai leggendo troppo nella parte "micro". Non significa sostituire ogni classe con un servizio di rete, ma strutturare un'applicazione monolitica in componenti di dimensioni ragionevoli, ognuna delle quali tratta un aspetto del programma. I servizi non si parleranno, quindi nella peggiore delle ipotesi hai diviso una grande richiesta di rete in più piccole. I dati restituiti non saranno significativamente diversi da quelli che ricevi comunque (anche se potresti restituire più dati e consolidarli nel client)


3
"I servizi non si parleranno." Immagino che i microservizi potrebbero avere dipendenze condivise (autenticazione, forse?) Che uno potrebbe separare in un altro microservizio. LDAP, in un certo senso, è un microservizio di autenticazione e immagino che tutti gli altri microservizi ne parlino. Oppure ... l'autenticazione avviene una sola volta? In che modo ciascun microservizio controlla le autorizzazioni rispetto all'autenticazione per prevenire attacchi con accesso diretto agli oggetti?
James Mishra,

2
@JamesMishra bene .. dipende. Quando ho usato l'ultima volta l'architettura dei microservizi, ciascun servizio era totalmente indipendente dagli altri per motivi di sicurezza (ma anche per motivi di silos aziendali). Auth è stato gestito da ciascuno in modo diverso, sebbene controllato da una politica di architettura. Tuttavia, non c'è motivo per cui non possano parlare con auth per esempio, o semplicemente avere auth basato su una libreria. Ma ... stavo cercando di dire che non avrebbero dovuto passare molte chiamate tra di loro, non che non avrebbero dovuto consumare servizi come clienti stessi.
gbjbaanb

@JamesMishra, auth è spesso il proprio servizio in questi ambienti, e quindi ogni servizio dovrebbe semplicemente usarlo piuttosto che fare una completa implementazione da solo.
Paul,

2

Strutturando il codice e l'accesso alle risorse in modo tale che il sistema risultante possa essere abbastanza flessibile da essere eseguito come un'applicazione monolitica o distribuita tramite configurazione. Se estrai il meccanismo di comunicazione dietro un'interfaccia comune e costruisci il tuo sistema tenendo presente la concorrenza, puoi facilmente ottimizzare tutto dopo aver profilato il tuo sistema e trovato i veri colli di bottiglia.


Un esempio per spiegare cosa intendo dire @mortalapeman: hai un'interfaccia java / c # IProductAvailibitiy in cui sono collegati tutti i consumatori di IProductAvailibitiy. Esiste anche una classe ProductAvailibitiyImpl che implementa questa interfaccia e un ProductAvailibitiyMicroservice che utilizza ProductAvailibitiyImpl. I consumatori possono essere configurati per utilizzare un ProductAvailibitiyImpl locale o un proxy remoto per ProductAvailibitiyMicroservice
k3b,

2

Vorrei aggiungere una prospettiva diversa, da un settore diverso con ipotesi molto diverse: simulazione distribuita (a livello di entità). Concettualmente, è molto simile a un videogioco FPS distribuito. Differenze chiave: tutti i giocatori condividono un certo stato: dove si trova il drago in questo momento; nessuna chiamata al database; tutto è contenuto nella RAM per la velocità e la bassa latenza, il throughput è meno rilevante (ma immagino che non sia possibile ignorarlo completamente).

Puoi pensare a ciascuna applicazione partecipante come un monolito (che rappresenta tutte le sfaccettature di un giocatore) o come un microservizio (che rappresenta solo un singolo giocatore in mezzo alla folla).

I miei colleghi hanno avuto interesse a scomporre una singola applicazione partecipante stessa, ulteriormente in microservizi più piccoli che potrebbero essere condivisi, ad esempio l'arbitrato sui danni o i calcoli della linea di vista, cose che sono solitamente raggruppate nelle simulazioni.

Il problema è la latenza di invio di chiamate e di attesa di richieste. La larghezza di banda è comunque irrilevante e abbondante, come altri hanno sottolineato. Ma se un calcolo della linea visiva va da 1 microsec a 100 microsec (diciamo, a causa della messa in coda nel nuovo microservizio condiviso tra tutte le applicazioni del lettore), si tratta di una perdita enorme (potrebbe essere necessario più o più calcoli della linea di vista per ogni aggiornamento, diversi aggiornamenti / secondo).

Pensa attentamente a come funzionano i servizi, quando vengono chiamati e quali dati vengono scambiati. Le nostre applicazioni non scambiano già solo informazioni sulla posizione, ma scambiano informazioni sulla resa dei conti morta - Sono nella posizione x, in direzione y alla velocità q. E non devo aggiornare le mie informazioni fino a quando tali ipotesi non cambiano. Molti meno aggiornamenti e la latenza (mentre è ancora un problema) arriva proporzionalmente meno frequentemente.

Quindi, piuttosto che richiedere un servizio a grana fine a una frequenza più elevata, prova a ridurre la frequenza:

  1. modifica dei dati richiesti e utilizzo dei calcoli locali
  2. invio di query o parametri di trigger per una risposta asincrona
  3. richieste di batch
  4. anticipare le richieste e preparare una risposta in anticipo, sulla speculazione (opposto della valutazione pigra)
  5. ove possibile, evitare microservizi chiamando altri microservizi; questo aggrava il problema, ovviamente. Capisco che questo sia un incentivo per aumentare i microservizi e in qualche modo sconfigge il punto, ma i microservizi non sono amici della latenza. Forse basta ammetterlo e superarlo.

Ora ricordati di controllare i tuoi presupposti sul tuo sistema. Se sei più interessato alla velocità effettiva che alla latenza, o non hai uno stato condiviso, ecc., Allora usa i microservizi dove hanno senso. Sto solo dicendo che forse non li usano dove non hanno senso.


1

La tua ingenua immaginazione è giusta. E spesso non importa. Le macchine moderne sono veloci. I principali vantaggi dell'architettura di micro-servizi sono rappresentati dallo sforzo e dai tempi di sviluppo e manutenzione.

E, naturalmente, non esiste una regola che dice che non è possibile utilizzare la memoria condivisa o distribuire fisicamente più servizi in un eseguibile. Fintanto che lo progetti per non dipendere da quello.


Le CPU sono veloci. La memoria è veloce Gli SSD sono veloci. Ma le schede di rete, i router e gli switch sono "veloci"? Un'altra risposta insiste, ma non ne sono sicuro.
James Mishra,

È sicuramente facile imbattersi in problemi di velocità della rete. Gestisci un servizio a San Francisco, un altro ad Amsterdam e consumali a Sydney. Il ritardo è la chiave, non la larghezza di banda. Quindi non farlo. E rendere i servizi grandi come un senso
Stephan Eggermont

1

Come molte persone hanno detto, non si tratta di colli di bottiglia della rete. Riguarda maggiormente la fragilità della rete. Quindi il primo passo è evitare la comunicazione sincrona. È più facile di quanto sembri. Tutto ciò che serve sono i servizi con i giusti limiti. I giusti confini si traducono in servizi autonomi, vagamente accoppiati e altamente coesi. Un buon servizio non ha bisogno di informazioni da un altro servizio, lo ha già. L'unico modo in cui i buoni servizi comunicano è attraverso gli eventi. Anche i buoni servizi sono eventualmente coerenti, quindi non ci sono transazioni distribuite.

Il modo per raggiungere questa bontà è identificare prima le capacità aziendali. La capacità aziendale è una specifica responsabilità aziendale. Un certo contributo al valore aziendale complessivo. Quindi ecco la mia sequenza di passi che prendo quando penso ai confini del sistema:

  1. Identificare le responsabilità aziendali di livello superiore. Ce ne saranno alcuni. Considera questi servizi come una procedura che la tua organizzazione dovrebbe percorrere per raggiungere il suo obiettivo di business.
  2. Approfondisci ogni servizio. Identificare i servizi di livello inferiore compresi quelli principali.
  3. Accanto ai primi due punti pensare alla comunicazione di servizio. Dovrebbero farlo principalmente tramite eventi, solo per informarsi reciprocamente in merito al risultato del loro processo aziendale. Gli eventi non devono essere considerati come trasportatori di dati.

Tieni presente che il servizio aziendale include persone, applicazioni, processi aziendali. Di solito solo una parte è rappresentata come autorità tecnica.

Questo potrebbe sembrare un po 'astratto, quindi probabilmente un esempio di identificazione dei confini del servizio sarebbe di qualche interesse.


0

Solo un altro fattore da aggiungere alle risposte correnti. Con servizi a grana grossa . Si desidera evitare la latenza di tutte le chiamate, quindi invece di effettuare 10 chiamate si effettua una chiamata che ottiene 10 pezzi di dati necessari in un DTO.

E ricorda che i microservizi non sono micro come pensano le persone.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.