Ti serve un servizio REST? Mvc vs Routing Middleware
Quando si realizza un servizio web bisogna sempre definire quello che sarà il perimetro di competenza del servizio per massimizzarne sicurezza e performance. A tale scopo potrebbe essere utile, nella realizzazione di un servizio RESTful, evitare l’utilizzo di MVC ma eseguire il route utilizzando il Routing Middleware sul quale MVC si basa.
Mvc e Routing Middleware: le differenze
Vediamo, prima di tutto, cosa cambia a livello di implementazione:
With mvc.
Il progetto è disponibile al seguente link Labs.MvcLover
WooController.cs
namespace Labs.MvcLover.Controllers |
Startup.cs
namespace Labs.MvcLover { |
Without mvc.
Il progetto è disponibile al seguente link Labs.MvcHater
WooEndpoint.cs
namespace Labs.MvcHater.Endpoints |
Startup.cs
namespace Labs.MvcHater
|
Notiamo che la differenza sostanziale risiede nel modo con il quale andiamo a definire la route: mentre nel primo caso andremo ad utilizzare il routing implicitamente offerto da MVC mediante app.UseMvc() all’interno del metodo Configure della classe Startup, nel secondo caso verrà definita una route puntuale mediante
app.UseRouter(router =>
|
Ok, ma perché mi dici questo?
Analizziamo, ora, cosa cambia a livello di performance.
Per eseguire i benchmark è stato utilizzato bombardier. Premessa: questi test sono stati eseguiti in ambiente locale, quindi i valori di latenza misurati sono inferiori a quelli che troviamo nel World Wide Web, ma danno, comunque, un’idea degli incrementi di performance raggiungibili con questo tipo di approccio.
Sfruttando il Routing Middleware otteniamo questo risultato #### Test A.
> bombardier -c 125 -n 10000 http://localhost:5000/api/woo
|
Test B
> bombardier -c 200 -d 10s -l http://localhost:5000/api/woo |
Mentre, utilizzando MVC, il risultato ottenuto è il seguente: #### Test A.
> bombardier -c 125 -n 10000 http://localhost:5000/api/woo |
Test B
> bombardier -c 200 -d 10s -l http://localhost:5000/api/woo |
Cosa notiamo se analizzassimo questi dati con la lente di ingrandimento?
Numero di richieste evase al secondo
More is better
Notiamo come nel test A le differenze di performace a favore di MvcHather siano superiori rispettivamente del: - avg: 356.79% - stdev: 327.70% - max: 267.58%.
Mentre nel test B le percentuali salgono a: - avg: 3750.67% - stdev: 714.98% - max: 605.64%.
Le maggiori prestazioni ottenute nel secondo test sono dovute al fatto che il servizio è riuscito a gestire meglio la concorrenza evadendo richieste più velocemente.
Latenza di risposta
Less is better
Questo test è la stretta conseguenza del precedente, dove la latenza è il delta risultante dalla data di invio della richiesta e la data di arrivo della risposta, in questo caso MvcHater performa meglio nel test A, ecco le percentuali: - avg: 311.43% - stdev: 489.47% - max: 566.34%.
Mentre nel test B le percentuali salgono a: - avg: 1011.40% - stdev: 1090.75% - max: 389.69%.
Volume di byte in uscita per secondo
More is better
Questo test serve per misurare il volume di byte in uscita dal servizio web, anche in questo caso MvcHater esce vincitore del 268.39% nel test A e del 667.26% nel test B.
Latenza distribuita
Less is better
Questo test serve a misurare il percentile di distribuzione della latenza per il quale otteniamo i seguenti valori:
% |
MvcLover |
MvcHater |
(MvcHater/MvcLover)% |
50% |
10.12 |
0.83 |
1219.27% |
75% |
10.17 |
1.02 |
997.06% |
90% |
10.17 |
1.19 |
854.62% |
95% |
10.20 |
1.45 |
703.45% |
99% |
10.20 |
1.64 |
621.95% |
Codici di risposta http
Qui possiamo notare come il servizio MvcHater sia riuscito ad evadere tutte le 2722 richieste ricevute in 10 secondi da 200 utenti concorrenti.
Mentre il servizio MvcLover ha evaso con successo solamente 84 richieste delle 284 ricevute, pari al 30%.
Il totale delle richieste evase con successo da MvcHater rispetto a MvcLover è superiore del 958%.
Conclusioni
Il framework MVC è sicuramente un valido strumento per realizzare siti web, ma sempre con più frequenza (n.d.r.: fortunatamente!) si sente parlare di applicazioni web moderne, in cui vi è netta distinzione fra front-end e back-end. In questo caso, ed esempio, basare l’implementazione del proprio back-end su tale framework potrebbe aggiungere overhead e quindi calo di performance.
In questi casi eseguire un routing attraverso il motore di generazione delle url di Microsoft.AspNetCore.Routing è sicuramente una scelta vincente e segue la buona pratica del less code is better.