Le code nei sistemi SaaS multi-tenant vengono spesso introdotte per migliorare la stabilità complessiva della piattaforma, migliorare l’esperienza utente e scalare il sistema. Se navighi su Internet o chiedi ad alcuni sviluppatori, spesso viene menzionata come una soluzione facile da implementare. In realtà, non è sempre così, e talvolta ci sono delle insidie che puoi incontrare durante questo processo.
Cosa significano realmente multi-tenancy e single-tenancy
Prima di tutto, rinfreschiamo alcuni concetti di base:
SaaS (Software as a Service)
SaaS è un modello di licenza e distribuzione software in cui il software è concesso in licenza su base di abbonamento ed è ospitato centralmente. SaaS è anche noto come software on-demand, software basato sul web o software ospitato sul web.
Multi-tenant
Significa che il software SaaS che offri serve più tenant/multipli client usando una singola istanza. Non importa se la tua istanza è un server, più server o serverless; l’importante è avere un’infrastruttura condivisa. La maggior parte delle aziende SaaS utilizza questo modello, poiché è molto più facile da gestire e riduce i costi di manutenzione complessivi. Infatti, solo servizi molto specializzati, con tariffe elevate, hanno senso senza essere multi-tenant.
Single-tenant
Opposto al multi-tenant. Significa che, per aggiungere un nuovo client, il team tecnico deve configurare una nuova istanza dell’app. Ogni tenant può avere anche una versione diversa dell’app (anche se mantenere troppe differenze spesso diventa costoso e difficile da gestire). In un sistema single-tenant, ogni nuovo client esegue una istanza software separata. Ogni tenant può avere più utenti che condividono la stessa istanza.
Architettura SaaS single-tenant vs multi-tenant
La decisione tra multi-tenancy e architettura single-tenant esula dallo scopo di questo articolo, ma la regola generale è scegliere ciò che è importante per te — la facilità di gestione di molti client (probabilmente centinaia o migliaia), o la possibilità di personalizzare ogni singolo tenant con modifiche di codice personalizzate. Altri motivi per scegliere un’architettura single-tenant possono includere la necessità di risorse di calcolo separate, isolamento dei dati, sicurezza dei dati e requisiti legali specifici. In generale, qualcosa che possiamo riassumere come isolamento dei tenant.
Qual è il problema delle code nei sistemi multi-tenant?
Immaginiamo un sistema in cui esiste un processo a lunga esecuzione che i client eseguono. Può essere qualsiasi cosa — dall’elaborazione di un file (importazione di un CSV, conversione di formato video), o qualsiasi altra cosa abbia senso, come il crawling di una pagina web.
In tali sistemi, può capitare che un client esegua così tanti task accodati da formare una lunga coda in attesa di essere gestiti.
Se il Client 1 esegue 1000 di questi task, tutti gli altri client (2, 3 ecc.) dovranno aspettare che questi 1000 task vengano completati. Questo accade perché le code sono, per impostazione predefinita, FIFO — first in, first out.
Coda FIFO di default
In questo caso, il Client 2 aspetterà ore per completare un semplice task, si arrabbierà rapidamente e potrebbe persino cancellare l’abbonamento. Perché dovrebbe aspettare un’ora o due per completare una semplice conversione?
In pratica, un client può influenzare l’esperienza di molti altri client consumando tutte le risorse di calcolo disponibili.
Cos’è l’elaborazione equa in un’architettura multi-tenant
Prima di entrare in dettagli tecnici, consideriamo cosa intendiamo per equità.
La risposta rapida è: un client che genera un carico elevato non dovrebbe danneggiare altri client. Dovremmo quindi processare i task del Client 2 e del Client 3 e poi continuare con i task del Client 1.
Tuttavia, in molti SaaS abbiamo diversi livelli di clientela. Non tutti i client sono uguali. Un client del livello più basso probabilmente dovrebbe avere meno priorità rispetto a un client Enterprise. Questo potrebbe significare, ad esempio, che la nostra decisione di business sia di gestire i client del top Tier quattro volte più velocemente rispetto a quelli del livello più basso. Ciò non significa processare tutti i task del top Tier prima degli altri, ma solo processarli un po’ più velocemente quando la coda è piena.
Architettura SaaS multi-tenant — aspetti da considerare
Isolamento dei dati — Single-tenant vs Multi-tenant
Quando si passa da un approccio single-tenant a uno multi-tenant, occorre considerare come partizionare i dati. L’applicazione memorizza dati di più tenant in un’unica istanza software, ma i dati dei tenant non dovrebbero essere condivisi tra di loro!
I tre modelli principali di multi-tenancy per l’archiviazione dei dati sono:
- Silo: ogni tenant ha una istanza separata di storage, ad esempio un database separato.
- Bridge: i dati di ciascun client sono memorizzati sullo stesso database, ma con uno schema separato per i dati.
- Pool: tutti i client condividono lo stesso database (compreso lo schema), ma le tabelle hanno colonne per identificare il tenant di appartenenza dei dati.
Modello Silo
L’approccio Silo è molto simile all’esecuzione di un’architettura single-tenant. Per lo storage DB, è necessario creare una nuova istanza per ogni client. Questo può essere automatizzato ed è più facile da gestire rispetto a creare una nuova istanza software per ogni client, ma richiede comunque molto lavoro e aumenta i costi di manutenzione.
Noisy neighbour
Nei SaaS multi-tenant, i client condividono le risorse hardware, quindi l’attività di un tenant può avere un impatto negativo sugli altri. Anche attività pesanti non accodate possono causare rallentamenti o errori per altri utenti. Questo accade non solo se tutti i tenant usano la stessa istanza di database, ma anche se condividono solo la stessa istanza software, poiché le risorse CPU sono condivise.
Come risolvere i problemi di code multi-tenant?
1. Aggiungere più worker
Può essere considerato un primo intervento se il problema si presenta. Più consumer possono ridurre i tempi di attesa. Tuttavia, un client può ancora bloccare gli altri, e di solito c’è un limite al numero di consumer eseguibili. Inoltre, se il processamento utilizza sistemi esterni o API, si rischiano facilmente limiti di rate.
2. Throttling delle richieste
È possibile introdurre limiti di quante richieste un tenant può fare in un certo intervallo. Non risolve la coda, ma aiuta a limitare il problema di tenant rumorosi. Ad esempio, si può mostrare un avviso all’utente che ha aggiunto troppi task, o suggerire l’upgrade a un tier superiore.
2.1 Throttling con priorità
Si può combinare il throttling con il livello del tenant. Molte code supportano la priorità dei messaggi, permettendo di processare più velocemente i client enterprise.
3. Sharding delle code
È possibile suddividere i task in più code. Ad esempio, dividendo i client in 3 code:
if client_id % 3 == 0:
inserisci_in_coda(coda_A, task)
elif client_id % 3 == 1:
inserisci_in_coda(coda_B, task)
else:
inserisci_in_coda(coda_C, task)
Se un client satura una coda, solo circa un terzo degli altri tenant sarà influenzato.
3.1 Sharding avanzato
Si possono creare code per i tenant enterprise o per quelli noti per carichi elevati. Ad esempio, una coda “spike” attivata da un meccanismo di rate-limiting può gestire i picchi di un tenant senza influenzare gli altri.
4. Code dedicate per tenant
Creare una coda per ciascun tenant (tramite automazione come CloudFormation o Terraform) è elegante e potente, ma diventa difficile da gestire se ci sono migliaia di nuovi tenant ogni settimana.
4.1 Gestione di molte code
- Eseguire un consumer per ciascun tenant pagante.
- Un consumer “snello” che cicla su tutte le code, prende massimo un task per coda e lo inoltra a una coda condivisa per l’elaborazione.
5. Cambiare ciò che si accoda
Invece di accodare ogni elemento, si accoda solo il fatto che un tenant deve importare dati. Il consumer prende un elemento alla volta e poi riprogramma il task nella coda, evitando di bloccare gli altri tenant.
while True:
task = prendi_task_import(client)
elemento = prossimo_elemento_da_importare(client)
importa(elemento)
rimetti_in_coda(task)
Rate limit e gestione dei tier
Si può calcolare un ritardo basato sui rate limit dell’API esterna, aumentando la distanza tra chiamate quando ci si avvicina al limite. Ogni tier può avere un moltiplicatore per regolare la velocità di elaborazione dei task import.
Non esiste una soluzione unica
La gestione delle code nei SaaS multi-tenant non ha una soluzione valida per tutti. È facile implementare una coda, ma ci sono molti problemi possibili: equità, isolamento dei dati e scalabilità. È utile ripensare l’approccio per il proprio sistema e adattarlo ai propri tenant. In generale, l’investimento nella corretta architettura multi-tenant vale la pena, riducendo i costi di manutenzione e migliorando l’esperienza utente.




