Internet Information Services (in inglese)

Scalare applicazioni ASP.NET: esperienza acquisita

Richard Campbell

 

Panoramica:

  • L'importanza della collaborazione tra sviluppatori e professionisti IT
  • Capire le strategie di scalabilità principali
  • Condividere la conoscenza tra i team
  • Concordare le competenze di base

Indice

I fondamenti della scalabilità
Riunire i team
Cosa hanno bisogno di sapere gli amministratori dagli sviluppatori?
Cosa hanno bisogno di sapere gli sviluppatori dagli amministratori?
Ancora sulla scalabilità
Uno sforzo comune

In qualità di consulente, la scalabilità dell'applicazione ASP.NET di cui mi sono occupato è sempre stata il risultato di uno sforzo congiunto fra gli sviluppatori (i realizzatori) e gli amministratori di rete (gli utilizzatori). Sfortunatamente, non sempre all'inizio dello sviluppo di un'applicazione

si considera indispensabile questa collaborazione. Non ho mai avuto l'opportunità di essere coinvolto sin dall'inizio dello sviluppo di un'applicazione. Sono stato chiamato in causa sempre verso la fase finale, cioè quella critica.

La verità è che nessuna applicazione scala efficacemente sin dall'inizio, è impossibile ottenere un risultato impeccabile nella prima versione. Per scalare un'applicazione in modo soddisfacente è necessario capire come è stata creata e l'ambiente nel quale viene eseguita. In altre parole, si ha bisogno di informazioni sia da parte degli sviluppatori che di coloro che si occupano della rete. Senza condividere entrambe le conoscenze non si può raggiungere un buon risultato.

I fondamenti della scalabilità

Prima di lanciarci nel pieno della questione, iniziamo vedendo cosa è necessario per scalare un'applicazione ASP.NET. Generalmente vengono utilizzate due strategie fondamentali: specializzazione e distribuzione. Le applicazioni ASP.NET scalabili più grandi fanno uso generalmente di entrambe le strategie. Tutte le dritte sulla scalabilità delle applicazioni ASP.NET presenti nei testi rientrano in qualche modo in una delle due strategie.

La specializzazione prevede la separazione degli elementi dell'applicazione così che essi possano essere scalati separatamente. Si potrebbero ad esempio creare server di immagini dedicati piuttosto che utilizzare gli stessi server impiegati per il rendering delle pagine di ASP.NET. La configurazione ottimale di un server di immagini è infatti abbastanza diversa da quella di un server ASP.NET. Separare le richieste di immagini dal resto dell'applicazione dà inoltre la possibilità di utilizzare risorse di terze parti. Lo stesso approccio può essere applicato ad altri tipi di risorse.

L'altra strategia menzionata prima, prevede invece la distribuzione simmetrica dell'applicazione su più server, i quali costituiscono una cosiddetta Web farm. Le applicazioni ASP.NET sono particolarmente adatte alla distribuzione perché ogni richiesta di pagina singola è abbastanza piccola e le interazioni tra gli utenti sono indipendenti. La strategia di distribuzione è la vera manifestazione della scalabilità orizzontale, dove più server dalle prestazioni medie lavorano insieme alle richieste degli utenti. Con la scalabilità verticale invece abbiamo un server con prestazioni altissime che si occupa di tutto.

Utilizzando contemporaneamente entrambi gli approcci si aumenta l'efficienza. È possibile ad esempio distribuire soltanto gli elementi dell'applicazione che richiedono prestazioni aggiuntive. Se si è creato un server di immagini dedicato, ma questa soluzione non risulta tuttavia adeguata, è possibile aggiungere altri server dello stesso tipo, piuttosto che per l'intera applicazione. È importante tenere presenti queste strategie per migliorare le prestazioni e la scalabilità della propria applicazione ASP.NET.

Riunire i team

Ad un certo punto del ciclo di vita di ogni applicazione ASP.NET è molto probabile che gli sviluppatori e il personale di rete/IT si debbano incontrare. Nel migliore dei casi questa riunione si terrà prima della distribuzione dell'applicazione. In alcuni casi però le due parti si incontrano soltanto dopo il sorgere di alcuni problemi, ad esempio quando l'applicazione funziona benissimo nell'ambiente di test, ma è lenta quando distribuita agli utenti. (È in casi come questi che consulenti come me vengono chiamati in causa).

Quando gli sviluppatori e gli amministratori di rete si incontrano, l'obiettivo primario è quello di confrontarsi. Gli sviluppatori conoscono l'applicazione nei dettagli, mentre gli amministratori di rete hanno una conoscenza più approfondita dell'ambiente di funzionamento. Gli uni devono capire i dati degli altri e prima si incontrano meglio è.

Questa riunione non dovrebbe essere organizzata soltanto al sorgere dei problemi. Senza una profonda sinergia fra i due team è estremamente difficile identificare le cause delle scarse prestazioni dell'applicazione. Inoltre, è troppo facile decidere a priori che il problema è causato da una mancanza da parte dell'altro team. Di fatto non è mai così. Entrambi i team devono cooperare per risolvere qualsiasi problema estremamente complicato.

Anche quando non ci sono problemi notevoli da affrontare, tali riunioni possono tuttavia essere realmente stimolanti. Le riunioni che ho seguito si sono generalmente svolte con gli amministratori da un lato del tavolo e gli sviluppatori dall'altro. Sembra che guardarsi negli occhi aiuti a risolvere i problemi. Per ottenere una discussione costruttiva, io sottolineo sempre lo scopo della riunione, appunto quello di scambiarsi conoscenza. Non importa chi inizia. Inizierò qui con ciò che gli amministratori hanno bisogno di sapere dagli sviluppatori.

Cosa hanno bisogno di sapere gli amministratori dagli sviluppatori?

Ogni applicazione ASP.NET ha le sue sfumature, ma ci sono degli elementi fondamentali comuni a tutte. Il file web.config è uno di questi (vedere Figura 1). Il file Web.config è un punto di incontro tra gli sviluppatori e il personale di rete. A volte sono i primi a configurarlo, mentre in altri casi sono gli amministratori a farlo. In ogni caso, ciò che è contenuto nel file web.config mette dei limiti alla configurazione hardware e di rete e ha un notevole impatto sul modo di operare dell'applicazione. Per analizzare ogni piccolo aspetto del file web.config non basterebbe un libro intero; ciò che è importante nella nostra discussione è che entrambi i team devono analizzare il file web.config e convenire sulla configurazione. Devono inoltre stimare l'impatto che le varie impostazioni avranno sull'applicazione e sull'ambiente.

fig01.gif

Figura 1 Un file web.config di base che mostra alcune impostazioni dell'applicazione e la configurazione personalizzata degli errori (fare clic sull'immagine per ingrandirla)

Ad esempio, la sezione <authorization> del file web.config specifica come gli utenti saranno autenticati nell'applicazione e definisce così una dipendenza. Se l'applicazione utilizza l'autenticazione di Windows®, allora essa potrebbe dipendere da Active Directory®. Se invece utilizza l'autenticazione basata su moduli, la dipendenza è su un archivio dati di account utente. Discutere tutto ciò è certamente estremamente utile.

È inoltre importante discutere la sezione <customErrors> in quanto essa riguarda il modo in cui gli errori verranno visualizzati agli utenti. Questa non è un'impostazione complessa, ma vale la pena discuterne per capire quali saranno le pagine di errore. All'inizio del ciclo collaborativo probabilmente non ci sono pagine di errore personalizzate e anche questo è un argomento da discutere.

Anche la sezione <appSettings> del file web.config può essere fonte di significative discussioni. È qui in genere che gli sviluppatori mettono in rilievo valori globali, come le stringhe di connessione ai database. Da questo argomento possono scaturire molte dipendenze e strategie per la pianificazione di failover, migrazione e così via. Dal momento che la sezione <appSettings> è interamente personalizzabile e di conseguenza può contenere moltissime impostazioni, un'ampia discussione potrebbe essere necessaria. Spesso in questa sezione si trovano valori che in realtà non vengono utilizzati in nessuna parte dell'applicazione.

Anche se gli sviluppatori non utilizzano <appSettings>, il personale di rete potrebbe volere utilizzare questa sezione. Infatti, avendo tutte le stringhe di connessione ai database, si potrebbe creare un'efficace e semplice strategia di failover. Se il server di database cessa di funzionare, può essere inserita una stringa di sostituzione per indicare a quale server alternativo puntare. Cogliere quest'opportunità nelle prime fasi del ciclo di sviluppo può aumentare l'affidabilità e la gestibilità dell'applicazione.

Un altro valore estremamente importante del file web.config per quanto riguarda la scalabilità è <sessionState>. Questo tag determina la posizione dove verranno memorizzati i dati della sessione dell'applicazione. Per impostazione predefinita, i dati della sessione vengono memorizzati "InProc" o nello spazio del processo dell'applicazione ASP.NET. Se i dati della sessione sono configurati come in-process il bilanciamento del carico di lavoro deve essere rafforzato. Le richieste di un utente verranno servite dal server nel quale risiedono i dati della sessione. Su questo argomento ci sarà una lunga conversazione tra gli sviluppatori e gli amministratori di rete dal momento che questa scelta ha un notevole impatto sulla scalabilità e sul failover. Discutere questo fattore nelle prime fasi del ciclo di vita dell'applicazione può risparmiare notevoli grattacapi in fase di debugging.

Quando la conversazione arriva allo stato della sessione, è facile definire i requisiti del bilanciamento del carico. Alcuni ambienti dispongono di hardware dedicato con varie funzionalità per gestire il bilanciamento del carico. Queste funzionalità avranno una certa valenza solo se l'applicazione sarà in grado di gestirle. Ho già visto casi in cui hardware per il bilanciamento del carico era utilizzato in abbinamento ad applicazioni ASP.NET con dati della sessione in-process. Di conseguenza, occasionalmente le sessioni venivano perse senza alcun motivo. Ciò che sembrava un bug nell'applicazione era in realtà un errore di configurazione.

Il personale di rete deve naturalmente sapere dagli sviluppatori quale schema di bilanciamento del carico può funzionare con l'applicazione. Entrambe le parti hanno qualcosa da aggiungere quando si tratta di discutere quali schemi di bilanciamento del carico sono disponibili e quali possono funzionare con l'applicazione. Discutere di questa parte della configurazione in una fase preliminare del ciclo di vita dell'applicazione potrebbe già aiutare a scartare uno schema in-process.

Quando un'applicazione ASP.NET è pronta per la distribuzione (o è già nella sua fase iniziale di distribuzione), lo staff degli sviluppatori avrà già un'idea abbastanza chiara sulle aree dell'applicazione che sono veloci o lente. E soprattutto sapranno quali parti dell'applicazione potrebbero costituire dei colli di bottiglia o fonti di errori. Se il personale di rete è a conoscenza di questi colli di bottiglia, può già prepararsi ad affrontare questi problemi e forse anche bloccarli sul nascere.

Ho lavorato una volta con un'applicazione che doveva caricare un enorme carico di dati ogni notte, durante i tempi di inattività dell'applicazione. Gli sviluppatori avevano creato il meccanismo di caricamento dei dati, l'avevano testato e ne conoscevano molto bene il funzionamento. Sapevano che era molto pesante per il database, ma allo stesso tempo lo ritenevano un metodo efficace e ottimale per la risoluzione del problema.

Ma non avevano mai comunicato al team di rete che questo processo esisteva o che era pianificato per l'esecuzione all'una del mattino, proprio quando veniva eseguito il backup del database. Il database è rimasto online, ma durante la fase di backup operava molto più lentamente, dal momento che tutte le transazioni dovevano essere trattenute nell'apposito registro.

Il problema venne identificato solo quando la concomitanza del processo di backup e del caricamento dei dati risultò nella mancanza di spazio libero su disco. Il problema venne risolto, dopo giorni di problemi, semplicemente spostando il caricamento dei dati alle tre del mattino.

Avere una conversazione preliminare su come gestire il carico di lavoro nell'applicazione può salvare una notevole mole di lavoro.

Cosa hanno bisogno di sapere gli sviluppatori dagli amministratori?

Il mio punto preferito in questo caso è il diagramma di rete. Troppo spesso gli sviluppatori vedono la rete come indicato in Figura 2, cioè non una vera è propria rete, ma semplicemente server Web, browser e Internet.

fig02.gif

Figura 2 La rete vista dagli sviluppatori (fare clic sull'immagine per ingrandirla)

La realtà, si sa, è invece molto più complessa. Un diagramma come quello in Figura 3, se pur semplificato, è già più vicino alla realtà. Guardando Figura 3 sorgono subito delle domande. Ad esempio: "In che modo gli utenti di una rete privata virtuale (VPN) lavorano con l'applicazione?" oppure "In che modo l'autenticazione di un utente interno differisce da quella di un utente pubblico?" e così via.

fig03.gif

Figura 3 La rete reale che gli sviluppatori devono capire (fare clic sull'immagine per ingrandirla)

Mostrare un diagramma di rete naturalmente non basta. È importante anche spiegare la rete nei dettagli, poiché è impossibile sapere esattamente quali elementi avranno impatto sull'applicazione, soltanto guardando un diagramma. È necessario spiegare a fondo l'effettivo processo di connessione degli utenti pubblici, VPN e interni. Discutere le varie regole di firewall che esistono, soprattutto in architetture di rete perimetrali più complesse, solleverà potenziali problemi dell'applicazione.

Sarebbe certamente meglio discutere di tutto ciò prima della distribuzione dell'applicazione o addirittura prima dell'inizio dello sviluppo. Ciò che è certo è che di tutto ciò a un certo punto bisogna parlare ed è fondamentale che tutti capiscano l'intero diagramma di rete.

I modelli di failover e ridondanza sono anch'essi competenza del team di rete. Senza alcun supporto software o almeno la conoscenza del funzionamento, questi modelli funzionano raramente come previsto. Un'altro argomento importante che merita una discussione dettagliata, riguarda i vari scenari di errore. Se è a disposizione un servizio di clustering sul database, questo avrà impatto sul codice utilizzato per accedere allo stesso. Le query, per esempio, possono essere eseguite nuovamente dopo un cambio di server? Se è disponibile un sito ridondante, come verranno replicati su questo sito? Come avviene il passaggio da un sito a un altro?

Ancora una volta, mettere a punto questi requisiti all'inizio del ciclo di sviluppo è consigliabile. Ma meglio tardi che mai. Tutti coloro che lavorano su un'applicazione devono conoscere questi aspetti. Non c'è niente di più frustrante che avere una soluzione di failover che non funziona quando ce n'è bisogno.

C'è infine un'altra risorsa di rete fondamentale che bisogna discutere insieme: i registri di produzione. Io consiglio sempre di mettere a disposizione i registri di produzione al team di sviluppo. La reazione tipica dei team di rete è "Richiedeteli e ve li inviamo". Non penso che questo sia un approccio adeguato. Infatti, è molto più efficace dare agli sviluppatori la possibilità di recuperare i registri stessi, generalmente da un backup.

I registri di produzione sono essenziali quando si presenta un problema. Sono spesso la migliore (e l'unica) fonte di veri dati empirici su ciò che è veramente successo. E sono ugualmente importanti in molte circostanze comuni. Quando gli sviluppatori hanno accesso costante ai registri di produzione, possono analizzarli per controllare come opera una nuova funzionalità. E questo è un modo molto potente per scoprire che la funzionalità non stia facendo qualcosa che non dovrebbe ed eventualmente correggere il problema. Quando tutti hanno accesso ai registri, si possono risolvere i problemi molto più rapidamente.

Ancora sulla scalabilità

La riunione tra gli sviluppatori e il personale di rete è fondamentalmente un occasione per discutere tutte le possibili questioni riguardanti la scalabilità di un'applicazione ASP.NET. L'ambiente effettivo nel quale opera l'applicazione ha impatto sul codice. Tutte le strategie sulla scalabilità influenzeranno il funzionamento all'interno dell'ambiente di esecuzione. Applicare una determinata strategia, come ad esempio separare le parti relative a SSL, potrebbe richiedere delle modifiche all'ambiente di rete e forse anche delle modifiche ai server stessi.

Perfino una modifica che riguarda apparentemente soltanto il codice, come ad esempio la memorizzazione nella cache, può avere impatto sull'ambiente. Questo perché se si memorizzano dati nella cache dell'applicazione ASP.NET, si diminuiscono le chiamate al database ma allo stesso tempo si aumenta l'utilizzo della memoria. Ne risulta che si potrebbe aumentare il numero di server ASP.NET a disposizione o il riciclo di thread di lavoro sul server, che avvierebbe eventi di controllo della rete.

Scalare un'applicazione ASP.NET ha un impatto sia sul team di rete che sugli sviluppatori e quindi è bene prendere decisioni condivise da tutti. Spesso da questa collaborazione verranno fuori soluzioni originali che i team non riuscirebbero a realizzare lavorando indipendentemente. Ad esempio, coloro che si occupano della rete potrebbero essere a conoscenza di soluzioni hardware disponibili nell'azienda in grado di aiutare gli sviluppatori a garantire le prestazioni e la scalabilità. Solo discutendo di tutti questi dettagli dell'applicazione e dell'ambiente verranno messe in luce queste possibilità.

Uno sforzo comune

Risorse per la scalabilità di applicazioni ASP.NET

Non bisogna necessariamente pensare a un problema di scalabilità come a una cosa negativa. Solitamente, infatti, questo è un segno positivo in quanto causato da un numero eccessivo di utenti collegati all'applicazione. Questo è indice che l'applicazione è apprezzata dagli utenti! Ma tuttavia bisogna che l'applicazione funzioni.

Altre volte il problema è causato da altri fattori: l'azienda può aver lanciato una promozione, qualcuno può aver scritto un post su un blog riguardante il sito o ancora un social network può avere indirizzato un altissimo numero di utenti verso il sito Web. Ci si trova all'improvviso a dovere difendere l'applicazione da questo picco di accessi. Come ci si può immaginare, è preferibile considerare questo scenario prima che esso si presenti nella realtà. Dimostrare come la collaborazione può aiutare un'organizzazione a superare questo genere di problemi è un modo straordinario per chiudere la riunione tra gli sviluppatori e gli amministratori di rete.

La prima domanda da porsi per fronteggiare il problema è "Come rilevare che il sito sta cedendo a causa del carico di accessi?" Troppo spesso la risposta è: "Ci arriva una segnalazione dal CTO (Chief technology officer)". Se il primo segno di un malfunzionamento al proprio sito Web è una chiamata dall'esterno, allora c'è veramente qualcosa che non va. Alcuni indici dovrebbero segnalare il problema prima che squilli il telefono. Di certo non aiuterà a evitare la telefonata, ma almeno ci sarà il tempo per prepararsi una risposta. Dire "Davvero?" al CTO non è propriamente una di quelle mosse che fa scattare la promozione.

Prossima domanda: "Chi viene chiamato prima?" Chi si occuperà della situazione? Generalmente un membro del team di rete riceve il primo avviso e quella persona potrebbe essere inesperta. È quindi necessario avere pronto un piano di riassegnazione del problema. Chi viene chiamato dopo? La vera sfida è avere una diagnosi rapida per scoprire la natura del problema. Se si tratta di un'interruzione di rete è una questione. Ma se è un problema di scalabilità, allora ci troviamo in tutt'altra situazione. Per quanto riguarda i problemi di scalabilità è opportuno coinvolgere un membro del team di sviluppo al più presto possibile.

Tutti coloro che sono coinvolti nella risoluzione del problema necessitano di informazioni chiare e quindi avere dei diritti di accesso efficaci è un fattore chiave. Lo scopo è raccogliere quante più informazioni possibili in modo da avere una diagnosi esaustiva e di conseguenza la possibile soluzione.

Spesso, se l'unica soluzione è quella di scrivere del codice, allora il problema sarà già sparito prima che gli sviluppatori avranno fatto il proprio dovere. È consigliabile prendere nota del problema per definire le priorità del codice e prevenire casi del genere nel futuro. Non ha molto senso tuttavia scrivere un blocco massiccio di codice e metterlo in produzione senza avere eseguito un test accurato. Regola numero uno da seguire quando si affronta un problema: mai peggiorare la situazione.

In casi di problemi di scalabilità, a volte la soluzione è semplicemente attendere. Si tratta di uno degli approcci possibili.

Allo stesso tempo, avere pianificato delle strategie per casi del genere aiuta ad avere molteplici piani d'azione. Avere uno sforzo congiunto da parte degli sviluppatori e del team di rete può risolvere problemi di scalabilità in brevissimo tempo. Forse anche in un tempo così breve da rendere quell'evento promozionale ancora più efficace.

In conclusione, il team di rete ha imparato che un'applicazione ASP.NET ben fatta e altamente scalabile rappresenta il risultato della collaborazione tra i creatori e gli utenti della stessa.

La collaborazione è inevitabile, dunque è meglio per iniziare prima con le riunioni tra i team per condividere informazioni. Lo scopo delle riunioni è creare intesa e accordo su tutti gli elementi dell'applicazione: cosa fa, come lo fa, da cosa dipende, come si comporta sotto sforzo e come fa fronte ai problemi che sorgeranno in un futuro.

Quando questa collaborazione è realmente efficace, il risultato è un'azienda agile che può affrontare rapidamente problemi e che è in grado di stabilire con chiarezza i punti chiave dell'applicazione che la renderanno stabile nel futuro.

Richard Campbell è un Microsoft Regional Director, MVP di ASP.NET e presentatore di .NET Rocks, un programma radiofonico trasmesso su Internet e rivolto agli sviluppatori .NET (visita dotnetrocks.com). Lavora da anni come consulente per le aziende e si occupa di prestazioni e scalabilità delle applicazioni ASP.NET. Richard è anche uno dei fondatori di Strangeloop Networks.

© 2008 Microsoft Corporation e CMP Media, LLC. Tutti i diritti riservati. È vietata la riproduzione completa o parziale senza autorizzazione.