Scroll Top
Via Antonio Amato, 20/22 84131 Salerno (SA)

3 Elementi essenziali per il successo di un’Architettura Software

Blog Nexsoft - Architettura software

(articolo redatto da Vito Carrozza)

L’architettura software è al centro del successo di qualsiasi applicazione. tre concetti fondamentali guidano la progettazione di un sistema SOFTWARE robusto: la scalabilità, l’availability e le performance.

In questo articolo, si esploreranno come questi aspetti sono strettamente interconnessi e come possono influenzare il comportamento e il funzionamento di un’applicazione software di successo. Inoltre, si esploreranno come questi concetti vengono formalizzati e presentati ad un cliente al fine di ottenere un giusto livello di agreement.

Performance: ottimizzazione delle prestazioni

Il concetto di performance misura quanto velocemente e in modo efficiente un sistema può rispondere alle richieste degli utenti. Un’architettura ben progettata deve garantire prestazioni elevate per offrire un’esperienza utente ottimale.
Da un punto di vista tecnico, il concetto di performance può essere riassunto in due termini importantissimi: tempo di risposta e throughput.

Quando dal browser si effettua un click su un link, ci si aspetta che la pagina web richiesta appaia sullo schermo in maniera istantanea. Chiaramente, ciò può accadere solo in situazioni ideali, in quanto è necessario un certo tempo tecnico durante il quale la nostra richiesta viene ricevuta dal server e viene poi spedita una risposta; questo tempo è il tempo di risposta. Volendolo esprimere in maniera formale, esso è la somma di due tempi:

  • Tempo di processamento: ossia il tempo speso a elaborare la richiesta, eseguire una certa business-logic necessaria al compito per il quale si è fatta la richiesta e inviare una risposta
  • Tempo di attesa: quando si invia una richiesta o il server spedisce una risposta, non è detto che essa venga pervenuta immediatamente al nostro sistema, ma bensì la richiesta o la risposta possono rimanere inattive per un certo tempo di attesa. Questo tempo comprende ad esempio il tempo di attesa nelle code, oppure il tempo di trasmissione su rete.

Per quando riguarda il throughput, invece, esso è la misura di quanto “lavoro” per unità di tempo il sistema riesce ad elaborare. Molto spesso, se si misura il concetto di lavoro in task, allora si dirà che il throughput del sistema si misura in “tasks al secondo” (task/s). Se il lavoro del sistema, invece, è quello di elaborare dati, allora il throughput del sistema si misura in bit/s, oppure in bytes/s o ancora in MegaByte/s.

Stando alle definizioni, quindi, per ottimizzare l’architettura dal punto di vista delle performance è necessario ridurre il tempo di risposta e aumentare il throughput. Il caching, la parallelizzazione e la distribuzione del carico sono strategie comuni per ottimizzare le prestazioni in quanto l’implementazione di una cache riduce i tempi di accesso ai dati ripetitivi, mentre la parallelizzazione consente di eseguire operazioni simultanee per sfruttare al massimo le risorse disponibili. Tuttavia, non bisogna trascurare minimamente la definizione di tempo di processamento, in cui è forte la componente relativa alla qualità del codice sviluppato: se la business-logic implementata ci mette troppo ad essere eseguita, allora questo tempo può anche crescere esponenzialmente!

Scalabilità: gestire carichi di lavoro crescenti

La scalabilità in un’architettura software è la misura della capacità del sistema di gestire un aumento del carico di lavoro in modo efficace, contenendo i costi e aggiungendo risorse all’architettura stessa.

Questo aumento può derivare da un numero crescente di utenti, transazioni o volumi di dati. Si immagini un nuovo social network in forte crescita e che viene usato da un numero di utenti sempre maggiore: se i suoi amministratori non avessero un modo per aumentarne la capacità di lavoro contenendo al contempo i costi, esso sicuramente avrebbe vita breve.

Esistono tre tipi di scalabilità:

  • Scalabilità verticale: si parla in questo caso di “scaling-up”. Si attua scalabilità verticale quando un’architettura preesistente viene potenziata e/o aggiornata. Ad esempio, nel caso di un’architettura single-server multiple-clients, l’aggiunta di un banco di RAM al server è un modo per scalare verticalmente l’architettura.
  • Scalabilità orizzontale: si parla di “scaling-out”. Si attua scalabilità orizzontale quando si aggiungono risorse all’applicazione sottoforma di nuove istanze. Ad esempio, in un’architettura multi-server multi-client, l’aggiunta di nuovi server fa in modo da scalare orizzontalmente il sistema.
  • Scalabilità organizzativa: o “di team”. La scalabilità organizzativa si riferisce alla capacità di un’organizzazione di adattarsi e crescere in modo efficace ed efficiente man mano che le sue dimensioni, il suo ambito operativo o le sue esigenze cambiano nel tempo. Nel caso dello sviluppo di architetture software, la scalabilità organizzativa si applica al team di sviluppo.
Figura 1: scalabilità verticale e orizzontale.

Volendo confrontare scalabilità verticale e orizzontale, sicuramente è più semplice scalare un sistema verticalmente in quanto non si necessita di cambiare il codice sorgente quanto si aggiunge una nuova risorsa; tuttavia, una specifica macchina ha un limite di aggiornabilità: è possibile aggiungere risorse, ad esempio, ad un server finché il suo hardware lo permette. Dopodiché è necessario applicare un upgrade talmente radicale che potrebbe consistere anche la sostituzione dell’intera macchina, il che potrebbe implicare dei costi particolarmente alti. Inoltre, in presenza di architetture single server, una specifica macchina costituisce un punto centralizzato che in caso di fallimenti potrebbe compromettere il funzionamento dell’intera architettura. La scalabilità orizzontale, d’altro canto, risolve il problema del singolo punto di fallimento, ma introduce, però, un certo overhead e complessità di gestione: un sistema multiple server deve funzionare come se fosse un unico corpo e questo implica la progettazione di modalità di sincronizzazione e cooperazione fra le istanze. Inoltre, almeno la prima volta che si aggiunge una nuova risorsa al sistema, è necessario cambiare il codice sorgente per accogliere la nuova istanza. Infine, non c’è limite al numero di istanze che è possibile aggiungere.
Per quanto concerne la scalabilità organizzativa, l’aggiunta di personale al team di sviluppo aumenta di sicuro la produttività. Tuttavia, è possibile incorrere in un degrado delle prestazioni lavorative: più persone, implica più difficoltà nel coordinare e nel gestire il team.

Avalilability: garantire l’accessibilità continua

L’availability è la capacità di un sistema di rimanere operativo e di erogare i servizi richiesti anche in presenza di guasti o problemi.
Da un punto di vista tecnico, esso è un indicatore percentuale che indica la probabilità che una certa architettura sia funzionante e accessibile all’utente.
Matematicamente, è calcolata come il rapporto di due tempi: il tempo entro il quale il sistema è operativo e disponibile all’utente (anche detto uptime) e il tempo totale di funzionamento del sistema stesso. Quest’ultimo è a sua volta espresso come la somma dell’uptime e il tempo di inoperatività del sistema (detto downtime).

equazione availability

Molto spesso, a causa della natura non deterministica dei casi reali, al posto di uptime e downtime si utilizzano altri due indicatori che sono:

  • MTBF (mean time between failures): tempo medio in cui il sistema è operante tra un fallimento e un altro
  • MTTR (mean time to recovery): tempo medio necessario al recupero del funzionamento dopo un fallimento
equazione availability

In casi ideali, si vorrebbe MTTR (o equivalente il downtime) uguale a zero. Tuttavia, in casi reali, è possibile ottenere solo una tendenza allo zero. Quando l’MTTR (o il downtime) è molto molto piccolo, si parla di sistemi ad “alta availability”. Un’architettura ad alta availability mira a minimizzare i tempi di inattività e a garantire che gli utenti possano accedere alle funzionalità dell’applicazione in qualsiasi momento.

Quando il dowtime o l’MTTR è basso, si hanno percentuali di availability vicinissime al 100% (99%, 99.9%, 99.99%, …). A livello di documentazione, un modo per dare un’idea di quanto questo valore è vicino al 100% è indicarlo usando la n-nines notation, ossia indicando l’availability contando il numero di “9” nella sua percentuale.
Ad esempio:

99.99% viene espresso come “4-nove” (4-nines)

Avalilability e tolleranza ai rischi

Un sistema ad alta availability è un sistema che permette di essere resiliente ai fallimenti. Esistono tre modi per ottenere un’alta availability comprendendo anche la tolleranza ai rischi.

1. Failure prevention: per prevenire i fallimenti bisogna eliminare ogni possibilità che essi possano verificarsi. Vi sono due modi per evitare che i fallimenti possano accadere:

a. Ridondanza: si riferisce alla duplicazione di risorse, componenti o informazioni in un sistema al fine di aumentarne la sicurezza e l’availability. In generale, quando si parla di ridondanza, si fa riferimento a una situazione in cui si dispone di risorse aggiuntive, oltre a quelle strettamente necessarie per garantire un’operatività continua in caso di guasti o malfunzionamenti. Ad esempio, si possono avere più fonti di alimentazione o più dischi rigidi in un sistema RAID per proteggere i dati in caso di fallimento di uno dei componenti. Esistono due tipi di ridondanza: temporale e spaziale: la prima si riferisce alla duplicazione che avviene in due momenti temporali distinti, mentre la seconda si riferisce alla duplicazione che avviene in uno stesso momento temporale, ma su macchine diverse.

b. Replicazione: si riferisce alla creazione e alla gestione di copie identiche di dati o servizi su più sistemi o posizioni geografiche. L’obiettivo principale della replicazione è migliorare le prestazioni, la scalabilità e la resilienza del sistema, distribuendo il carico di lavoro su più risorse e riducendo il rischio di perdita di dati in caso di guasti o interruzioni. Ad esempio, i database possono essere replicati su più server per garantire una maggiore availability e ridurre il tempo di ripristino in caso di problemi.

Per applicare i concetti di ridondanza e replicazione, esistono due pattern architetturali molto importanti:

  • Active-to-active architecture: all’interno del sistema esistono più repliche di una certa risorsa che viene interrogata dall’utente. Quando viene effettuata una richiesta verso questa risorsa, la richiesta viene passata a tutte le repliche e la risposta generata è unica e viene formulata sulla base delle singole risposte ottenute dalle repliche.
  • Active-to-passive architecture: esiste un’unica replica primaria e molte repliche secondarie. Quando si effettua una richiesta verso una risorsa, l’unica replica a rispondere è quella primaria. Allo stesso tempo, le repliche secondarie ricevono degli snapshot periodici della richiesta dalla replica primaria, affinché quando la prima replica viene meno, esse possano rispondere alla richiesta e consentire così la fruibilità della risorsa.
Figura 2: architettura active-active
Figura 2: architettura active-active

 

 

Figura 3: active-passive architecture

 

2. Failure detection e isolamento: vengono utilizzati degli speciali sistemi di monitoring che sono in grado di interpretare le situazioni di fallimento e di raccogliere informazioni su di essi. In base a quest’ultime, questi sistemi sono in grado di disattivare la risorsa (affinché non venga più interrogata) e di passare il controllo ad eventuali altre repliche funzionanti.

3. Recovery from failures: recupero della corretta funzionalità a seguito di un fallimento. Esistono diverse strategie per effettuare il recovery a seguito di un fallimento. Qui se ne elencano alcune:

a. non inviare ulteriori richieste verso la falla, al fine di evitarne il sovraccarico e l’aggiunta di ulteriori problemi
b. riavviare la risorsa
c. effettuare il rollback a una versione precedente stabile

SLA, SLO, SLI: regolamentazione con il cliente

Quando si tratta di fornire o utilizzare servizi digitali, è cruciale stabilire standard di prestazione chiari e misurabili concordati fra il team di sviluppo e il cliente.
Gli SLA, o Service Level Agreement (Accordi a Livello di Servizio), sono gli strumenti contrattuali che definiscono questi standard. Essi sono a tutti gli effetti dei contratti legali inscindibili.
Gli SLO, o Service Level Objective (Obiettivi a Livello di Servizio), invece, sono gli strumenti che rendono le caratteristiche di performance, availability e scalabilità misurabili e tangibili; essi stabiliscono gli obiettivi da raggiungere. Ad esempio “il sistema deve avere un’availability di 4-nove” è uno SLO.
Gli SLI, o Service Level Indicator (Indicatori di Livello di Servizio), infine, forniscono le metriche concrete per valutare se gli obiettivi discussi negli SLO sono stati raggiunti.

Conclusioni: interconnessione tra Scalabilità, Disponibilità e Performance

La scalabilità, l’availability e le performance sono interdipendenti. Un sistema scalabile può gestire più carico, il che può contribuire a migliorare le prestazioni, ma solo se l’availability è garantita. Allo stesso modo, una migliore availability può migliorare l’esperienza utente, ma solo se il sistema è progettato per scalare in modo efficiente.

In conclusione, la scalabilità, l’avaliability e le performance sono tre pilastri fondamentali di un’architettura software robusta. Il successo di un’applicazione dipende dalla capacità di crescere con il carico di lavoro, rimanere accessibile in ogni momento e fornire prestazioni ottimali agli utenti. L’interconnessione tra questi aspetti richiede una progettazione olistica e un impegno continuo per migliorare e adattare l’architettura alle sfide in evoluzione del mondo tecnologico.


Se anche tu vuoi far parte del team di sviluppo Nexsoft,
dai un’occhiata alle nostre opportunità di lavoro e conosciamoci subito!

Questo sito utilizza cookies propri e si riserva di utilizzare anche cookie di terze parti per garantire la funzionalità del sito e per tenere conto delle scelte di navigazione.
Per maggiori dettagli e sapere come negare il consenso a tutti o ad alcuni cookie è possibile consultare la Cookie Policy.

USO DEI COOKIE

Se abiliti i cookie nella tabella sottostante, ci autorizzi a memorizzare i tuoi comportamenti di utilizzo sul nostro sito web. Questo ci consente di migliorare il nostro sito web e di personalizzare le pubblicità. Se non abiliti i cookie, noi utilizzeremo solo cookies di sessione per migliorare la facilità di utilizzo.

Cookie tecnicinon richiedono il consenso, perciò vengono installati automaticamente a seguito dell’accesso al Sito.

Cookie di statisticaVengono utilizzati da terze parti, anche in forma disaggregata, per la gestione di statistiche

Cookie di social networkVengono utilizzati per la condivisione di contenuti sui social network.

Cookie di profilazione pubblicitariaVengono utilizzati per erogare pubblicità basata sugli interessi manifestati attraverso la navigazione in internet.

AltriCookie di terze parti da altri servizi di terze parti che non sono cookie di statistica, social media o pubblicitari.