In microservice, si tratta di un singolo database o di una singola istanza di database per ciascun servizio?


51

Comprendo che ogni servizio in un'architettura di microservizi dovrebbe avere il proprio database. Tuttavia, avere un proprio database, significa in realtà avere semplicemente un altro database all'interno della stessa istanza del database o avere letteralmente un'altra istanza del database?

Con questo, non intendo la condivisione di database, che è un no-no, ma piuttosto l'istanza del database.

Ad esempio, se stavo utilizzando AWS e disponessi di 3 servizi, creo 3 database per ogni servizio su una singola istanza RDS o creo 3 istanze RDS contenenti ciascuna un database che viene utilizzato indipendentemente da ciascuno dei 3 servizi?

Se l'utilizzo di più database su una singola istanza RDS è un'idea migliore, vanificherà lo scopo di disporre di servizi indipendenti perché per:

  1. La risorsa dell'istanza RDS verrà condivisa tra i servizi. Il servizio A che può avere un uso intenso del database in un determinato momento avrà un impatto sul servizio B che utilizza un database diverso ma sulla stessa istanza RDS?

  2. Tutti i servizi dipenderanno dalla versione del database su quell'istanza RDS.


8
È qualunque cosa soddisfi al meglio le tue esigenze specifiche.
Robert Harvey,

1
Non sono sicuro che mi definirei un esperto di "microservizi" ma potresti avere qualsiasi tipo di configurazione e dbs. Potresti avere un db che viene letto da un servizio e scritto da un altro. O in alternativa potresti avere solo 1 db (o meno tecnicamente) per l'intero sistema.
Mark Rogers,

Ecco una buona lettura in merito: plainoldobjects.com/2015/09/02/…
RandomUs1r

Leggi "Principio della singola responsabilità". Hai pensato di implementare un "microservizio di database" utilizzato da altri microservizi?
ChuckCottrill,

Risposte:


21

Dipende molto dai requisiti di scalabilità e da come / se le istanze dei microservizi devono collaborare per fornire un unico risultato. Aiuta a sapere quali sono i compromessi:

Conservando tutto in un unico database

  • Configurazione più semplice
  • Non è necessario alcun coordinamento o comunicazione con altre istanze del servizio
  • È più facile scoprire il set di dati completo
  • Prestazioni del sistema limitate dalle prestazioni del database

Mantenere separati i database

  • La risposta completa per una richiesta può essere distribuita tra istanze di microservizi
  • In tal caso hai aumentato la comunicazione e la negoziazione per risolvere la richiesta
  • Gestione dei dati quando si perde quel nodo microservizio (anche quando il database è ancora attivo, non è possibile ottenerlo fino a quando non viene ripristinato un nuovo con la configurazione corretta)
  • Maggiore complessità della configurazione

Qual è il problema che stai risolvendo?

In alcuni casi, sei solo preoccupato per i dati effimeri. Se il database non funziona, non è un grosso problema. In quei casi potresti non aver nemmeno bisogno di un database per cominciare. Tieni tutto in memoria e rendi le cose incredibilmente veloci. Questa è la soluzione più semplice con cui lavorare.

In altri casi, è necessaria l'integrità dei dati, ma il database è in grado di espandere la sua capacità in base al numero di nodi che ha. In questo caso, un singolo database è probabilmente più che sufficiente e gestirne la reattività in modo indipendente è la risposta giusta.

Ci sono un certo numero di casi in mezzo. Ad esempio, potresti avere database specifici per regione, quindi per ogni istanza del tuo servizio in una regione diversa hai un database separato. In genere i database di sharding non funzionano bene tra le regioni, quindi questo è un modo per localizzare un po 'i dati e controllare da soli il coordinamento.

Dottrina e realtà

Ho letto una serie di articoli sui microservizi e su come dovrebbero essere modulari. Le raccomandazioni vanno dal mantenere il front-end, il microservizio e il livello dati come un'unità intera alla condivisione di database e / o codice front-end per tutte le istanze. Di solito, un maggiore isolamento offre la massima scalabilità, ma comporta un aumento della complessità.

Se il tuo microservizio è pesantemente calcolato, ha senso consentire il numero di quei microservizi in base alle necessità - la condivisione del database o il codice front-end non danneggiano o ostacolano questo approccio.

La realtà è che le esigenze specifiche del tuo progetto avranno bisogno di una serie diversa di compromessi per portare a termine il lavoro in modo tempestivo e gestire il carico di sistema che stai misurando (oltre a un po 'di più). Considera l'obiettivo completamente isolato front-end, microservizio e livello di dati. Maggiore è la domanda sul tuo sistema, più vicino a tale obiettivo probabilmente dovrai essere. Non siamo tutti [insert name of highly successful web entity here]e non hanno iniziato dove sono adesso. A volte devi solo iniziare con una situazione meno che perfetta ed esserne felice.


72

Supponendo che si disponga di alcuni servizi che possono utilizzare lo stesso tipo di sistema DB e versione, se si utilizzano istanze di database o db diverse è una decisione che non è necessario prendere in fase di progettazione. Invece, dovresti essere in grado di prendere la decisione al momento della distribuzione, qualcosa che puoi semplicemente configurare. Progetta i tuoi servizi in modo che siano indipendenti dal luogo in cui sono ospitati i database di altri servizi.

Durante il funzionamento, è possibile iniziare con un'istanza e, se il sistema funziona correttamente, lasciarlo così. Tuttavia, se noti che questo non si adatta bene al tuo sistema, poiché database diversi su un'istanza condividono troppe risorse, hai sempre la possibilità di utilizzare istanze diverse, se ciò aiuta.

Quindi un servizio non viola l'architettura dei microservizi solo perché si consente a due di loro di condividere alcune risorse, ma le viola quando la condivisione delle risorse diventa obbligatoria.


Questo tipo di suono sembra un'ottimizzazione prematura. Cosa succede se le risorse consumate non meritano mai istanze extra? Poi hai perso tempo a costruire la flessibilità
reggaeguitar,

5
@reggaeguitar: i costi per questo dovrebbero essere normalmente trascurabili - in effetti, per un'architettura a microservizi, potrebbe essere più impegnativo cercare di centralizzare la configurazione del database tra servizi diversi piuttosto che mantenere la posizione del db per ciascun servizio configurabile individualmente. Inoltre, il punto centrale di un'architettura di microservizi è l'elevata scalabilità, se uno non ne ha bisogno, non si dovrebbe prendere una decisione per i microservizi in primo luogo.
Doc Brown,

1
@DocBrown Questo ha senso, grazie per la risposta!
reggaeguitar,

13

Non importa

L'unico scenario in cui potrebbe teoricamente essere importante è se un servizio deve migrare verso versioni diverse del database. Ma anche in questo caso, non vi è alcuna reale differenza tra avere istanze separate dall'inizio rispetto alla migrazione di un servizio da un'istanza condivisa a un'altra. In realtà direi che avere istanze separate solo per questo scenario è un esempio di YAGNI.


1
Supponendo che se un determinato servizio ha un utilizzo intenso in una singola istanza RDS, finirà per consumare le risorse su quell'istanza e influenzerà gli altri servizi che utilizzano quella stessa istanza RDS?
xeno

1
@xenon: sì, ma questo è un motivo per pensare a migliorare le prestazioni RDS tramite tuning, hardware o cluster migliori, non a cambiare l'architettura del sistema - se quel servizio sta lasciando capacità per gli altri servizi, presto si esaurirà la capacità tutto da solo. Anche se immagino che potresti avere requisiti speciali che un servizio sovraccarico non deve influenzare gli altri. Alcuni RDS possono infatti ancora consentire ciò su una singola istanza definendo limiti di risorse su base utente.
Michael Borgwardt,

lo scenario in cui è importante è quando l' istanza del microservizio ha il suo stato. Quindi dovrebbe essere distribuito con la propria istanza db, che potrebbe anche essere un collo di bottiglia nelle prestazioni
Ewan

3

Un'istanza RDS è una casella singola. Se si dispone di più database su una singola istanza, questi condividono la CPU / memoria ecc.

Se le prestazioni del microservizio sono vincolate dalle prestazioni del database : quindi distribuire più copie del microservizio, ognuna utilizzando un database diverso, ma con ciascun database nella stessa istanza RDS. È inutile * (ad eccezione del failover). Il cluster di microservizi funzionerà alla stessa velocità di un singolo microservizio

Tuttavia , direi che un microservizio vincolato dalle prestazioni del database è insolito.

Di solito il microservizio ottiene i dati da un db, esegue un po 'di logica e riscrive alcune informazioni nel database. Il collo di bottiglia delle prestazioni è la logica , non la selezione e / o l'inserimento.

In questo caso puoi semplicemente condividere lo stesso database in tutte le tue istanze di microservizi


Devo mettere in discussione la tua affermazione che la logica è il collo di bottiglia, non il database. Nella mia esperienza, il posto più probabile per trovare miglioramenti delle prestazioni è con il database.
RubberDuck,

hmm sì, ma sicuramente quei miglioramenti delle prestazioni si ottengono spostando la logica fuori dal db e nel servizio. Una volta fatto ciò, POI la logica è il collo di bottiglia
Ewan,

1
In genere no. Tali miglioramenti derivano dall'ottimizzazione di indici e query.
RubberDuck,

bene, questo cadrà nel caso insolito della mia esperienza. Non che in genere non ci sia spazio per questi miglioramenti, ma che dopo aver rimosso qualsiasi elemento davvero negativo il database è ancora il fattore limitante.
Ewan,

1

L'obiettivo di mantenere un database privato per un servizio è l'incapsulamento. Il microservizio è una scatola nera che altri servizi nel sistema utilizzeranno tramite un'interfaccia pubblica.

Esistono due piani su cui opera questo incapsulamento:

  • Il primo è logico, a livello di applicazione. Il tuo servizio possiede alcuni oggetti business nel tuo sistema e deve mantenere lo stato su questi oggetti. Che un determinato database supporti questi oggetti business è solo un dettaglio dell'implementazione. Mantenendo un database separato, si impedisce ad altri servizi di avere accesso backdoor alla propria implementazione, costringendoli a utilizzare invece l'interfaccia pubblica. L'obiettivo qui è un'architettura pulita e una programmazione disciplinata. La posizione esatta del database è irrilevante a questo livello, a condizione che il servizio disponga dei dettagli di connessione corretti per poterlo trovare.

  • Il secondo livello è operativo. Anche se il tuo design è una scatola nera perfetta, come fai notare, lavori diversi associati a una singola macchina possono competere per le risorse. Questa è una buona ragione per mettere database logici separati su macchine separate. Come hanno notato altre risposte, se le tue esigenze non sono molto esigenti e il tuo budget è limitato, questo è un argomento pragmatico per la collocazione su una singola macchina. Tuttavia, come sempre, compromessi: questa configurazione potrebbe richiedere più babysitter man mano che il sistema cresce. Se il budget lo consente, preferisco quasi sempre due piccole macchine separate per eseguire due attività rispetto alla condivisione di una macchina più grande.


1

Penso che potrebbe essere di aiuto essere un po 'più teorico qui. Una delle idee motivanti alla base dei microservizi è la condivisione del nulla, i processi di passaggio dei messaggi. Un microservizio è come un attore nel modello Actor. Ciò significa che ogni processo mantiene il proprio stato locale e l'unico modo per un processo di accedere allo stato di un altro è inviare messaggi (e anche in questo caso l'altro processo può rispondere come piace a quei messaggi). Ciò che si intende per "ogni microservizio ha il proprio database" è in realtà che lo stato di un processo (cioè microservizio) è locale e privato . In larga misura, ciò suggerisce che il "database" dovrebbe essere collocatocon il microservizio, cioè il "database" deve essere memorizzato ed eseguito sullo stesso nodo logico del microservizio. Diverse "istanze" del microservizio sono processi separati e quindi dovrebbero avere ciascuno il proprio "database".

Un database globale o un database condiviso tra microservizi o persino istanze di un microservizio costituirebbe, da questa prospettiva, uno stato condiviso. Il modo "appropriato" di gestirlo dal punto di vista dei microservizi è quello di avere il database condiviso mediato da un microservizio "database". Altri microservizi che volevano conoscere il contenuto del database avrebbero inviato messaggi a quel "microservizio di database". Questo in genere non eliminerà la necessità di stato locale (cioè per "database" di istanza del microservizio) per i microservizi originali! Ciò che cambia è ciò che rappresenta lo stato locale. Invece di memorizzare "L'utente Sally è un amministratore", memorizzava "Il microservizio del database diceva 'Utente Sally è un amministratore' cinque minuti fa". In altre parole, sullo stato di altri microservizi.

Il vantaggio di questo è che ogni microservizio è autonomo. Questo rende un microservizio un'unità atomica di guasto. (Per lo più) non devi preoccuparti di un microservizio in uno stato parzialmente funzionale. Naturalmente, il problema è stato spostato nella rete di microservizi. Un microservizio potrebbe non riuscire a eseguire la funzione desiderata a causa dell'incapacità di contattare altri microservizi. Il vantaggio, tuttavia, è che il microservizio sarà in uno stato ben definito e potrebbe essere in grado di offrire un servizio degradato o limitato, ad esempio lavorando su convinzioni obsolete. Il rovescio della medaglia è che è molto difficile ottenere un'istantanea coerente del sistema nel suo insieme, e possono esserci parecchi ridondanze e duplicazioni (indesiderate).

Naturalmente, il suggerimento non è quello di inserire un'istanza di Oracle in ogni contenitore Docker. Innanzitutto, non tutti i microservizi richiedono un "database". Alcuni processi non richiedono alcuno stato persistente per funzionare correttamente. Ad esempio, un microservizio che si traduce tra due protocolli non necessita necessariamente di uno stato persistente. Per quando è necessario uno stato persistente, la parola "database" è solo una parola per "stato persistente". Può essere un file con JSON in esso o un database Sqlite o una copia locale di Oracle se lo desideri o qualsiasi altro mezzo di localmentememorizzazione persistente dei dati. Se il "database" non è locale, quindi da una prospettiva di microservizi puri, dovrebbe essere trattato come un (micro) servizio separato. A tal fine, non ha mai senso avere un'istanza RDS come "database" per un microservizio. Ancora una volta, la prospettiva non è "un mucchio di microservizi con i propri database RDS" ma "un mucchio di microservizi che comunicano con i database RDS". A questo punto non fa alcuna differenza se i dati sono archiviati nella stessa istanza del database o meno.

Pragmaticamente, un'architettura di microservizi aggiunge un'enorme quantità di complessità. Questa complessità è solo il prezzo per affrontare seriamente un fallimento parziale. Per molti, è eccessivo che probabilmente non vale i vantaggi. Dovresti sentirti libero di progettare il tuo sistema in qualunque modo sembri più vantaggioso. C'è una buona possibilità che preoccupazioni sulla semplicità e l'efficienza possano portare a deviazioni da una pura architettura di microservizi. Il costo sarà un ulteriore accoppiamento che introduce le proprie complessità come interazioni invisibili tra servizi e restrizioni sulla libertà di implementazione e ridimensionamento a piacere.


"a causa dell'incapacità di contattare altri microservizi." - Pensavo che i microservizi non dovessero mai contattare altri microservizi?
Marc
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.