Performance della Session

3 visualizzazioni
Passa al primo messaggio da leggere

Gianni

da leggere,
5 giu 2008, 03:54:0005/06/08
a
Ciao a tutti,

esiste un tool che possa analizzare gli oggetti Session sul server per poter
vedere quante risorse occupano i singoli oggetti (collezzioni, datatable ecc)
posti all'interno della Session stessa?

Grazie
Gianni

Matteo Migliore

da leggere,
5 giu 2008, 15:31:4405/06/08
a
> esiste un tool che possa analizzare gli oggetti Session sul server per
> poter
> vedere quante risorse occupano i singoli oggetti (collezzioni, datatable
> ecc)
> posti all'interno della Session stessa?

Puoi usare i Performance Counters:
http://support.microsoft.com/kb/815159

Attenzione che la Session va usata
con cautela; per rendere persistenti
informazioni temporanee ci sono sistemi
più solidi :-). Questo non vuol dire di non
sfruttarla in modo assoluto, ma di ragionare
nel farlo.

> Grazie

Prego! ;-)

--
Matteo Migliore
Blog: http://blogs.ugidotnet.org/matteomigliore

Gianni

da leggere,
6 giu 2008, 05:24:0006/06/08
a

"Matteo Migliore" wrote:

Ciao Matteo e grazie per la risposta!
Dato che hai scritto di fare attenzione all'utilizzo dell'oggetto Session e
visto che sono perfettamente d'accordo con te, ti chiederei dove inserire le
informazioni che mi servono a livello di utente connesso.
Io ho sempre usato la Session, l'Application (x quelle relative all'intero
sito a differenza di Session) e la Chache (x quelle temporanee a cui do una
scadenza in minuti).
Esempio l'istanza di classe di mapping dell'utente loggato o un oggetto di
Business in che supporto li archivieresti?
Hai diverse soluzioni a questi 3 oggetti?

Grazie di nuovo Matteo
Gianni

Mauro Servienti [MVP]

da leggere,
6 giu 2008, 11:18:2906/06/08
a
Ciao Gianni,

You wrote on 06/06/2008 :
> Dato che hai scritto di fare attenzione all'utilizzo dell'oggetto Session e
> visto che sono perfettamente d'accordo con te, ti chiederei dove inserire le
> informazioni che mi servono a livello di utente connesso.

Nella Session :-D

mi intrometto... perchè il discorso mi sta molto a cuore

Vediamo prima di capire queli sono i problemi legati alla Session e poi
cerchiamo di capire come arginarli o per meglio dire pararci il c*lo
:-)

E' evidente che in una applicazione web *hai* bisogno in alcune
circostanze di mantenere lo stato tra una chiamata e l'altra, purtroppo
http è disconnesso e quindi questa cosa si deve fare sul server (si lo
so c’è anche il ViewState ma imho è quasi sempre un’arma a doppio
taglio), la tentazione di mettere tutto in sessione è abbastanza alta e
sembrerebbe una soluzione rapida ed indolore ma... ci sono casi in cui
è necessario pensare che l'applicazione che stai scrivendo è
un'applicazione enterprise e quindi potenzialmente soggetta a:

- elevato(issimo) traffico;
- elevatissima mole di dati trattati;
- necessità di poter scalare orizzontalmente (load balancing) in
maniera trasparente, non deve essere cioè necessario modificare il
codice dell'applicazione all'aggiunta o rimozione di server e
l’applicazaione, e qui sta il trucco, deve beneficiare di questa
operazione;

In uno scenario del genere la session può portare a "qualche" (grosso
se non addirittura insormontabile) problema:

- Essendo http disconnesso il server non può sapere se un utente
tornerà, potrebbe banalmente aver chiuso il browser e tu non puoi
saperlo, in questa situazione i dati rimangono in sessione per il tempo
di timeout (di default 20') della sessione stessa e non ci puoi fare
nulla. Se quindi guardi la macchina in un istante t potresti avere una
fotografia delle prestazioni della macchina mostruosamente falsata
perchè potresti avere una macchina in memory pressure ma con nessun
utente realmente connesso;

- la sessione non scala orizzontalmente: in caso di load balancing se
usi la sessione le chiamate successive di un utente x vengono
continuamente soddisfatte dalla stessa macchina e questo è male e puoi
ben immaginare le conseguenze. Tutto ciò potrebbe portarti ad avere una
farm il cui carico è distribuito malissimo proprio per il problema
esposto al punto precedente, inoltre si potrebbe supporre di aggiungere
hw senza minimamente spostare il problema...

Vediamo le possibili soluzioni con pregi e difetti:

- distinguere *sempre* quando è necessario mettere in sessione e quindo
è meglio "caricare e dimenticare", quindi ad esempio una paginetta che
visualizza l'elenco dei clienti:

* carico i clienti (tutti o paginati poco importa) da db e li metto in
sessione perchè dico così appena l'utente vuole i dettagli di uno li ho
già li... e non li devo ricaricare... ma se non li guarda tutti i
dettagli ho sprecato un sacco di risorse
* carico i clienti (paginati) li metto in binding con la griglia e
butto via tutto. del resto in questa fase sono in sola lettura, se
l'utente fa F5 sul browser rifaccio tutto, faccio un po’ di lavoro in
più ma faccio solo lo stretto necessario che l’utente mi ha chiesto...
non cerco di prevedere le sue mosse (del resto non è semplice)

nel primo caso incappi nel problema della sessione che vive oltre la
presenza dell'utente nel secondo invece hai una situazione opposta:
fotografando la macchina in un momento t potresti avere quasi sempre
una situazione decisamente accettabile e solo alcuni limitati picchi
(veri picchi) che sono quelli corrispondenti ai momenti di elaborazione
(tante risorse per poco tempo, contro medie risorse per tanto tempo).
In questa situazione ti potresti giustamente trovare nei guai al
crescere degli utenti che potrebbero portare alla saturazione delle
risorse in fase di elaborazione ma in questo scenario sei perfettamente
"scalable aware" cioè se metti il tutto in load balancing
l'applicazione non se ne accorge neanche e il tutto (ri)comincia a
funzionare come si deve, usando la session questo sarebbe impossible.

Sappiamo anche che hai un'opzione "out of process/state server" per la
session che ti permette di scalare orizzontalmente ma:

- tutto ciò che finisce in session deve essere serializzabile;
- le prestazioni sono quelle che sono perchè la
serializzazione/deserializzazione è generica e costosa...
- hai un single point of failure: la macchina che gestisce le sessioni
out of process;

Come però sappiamo il mondo non è fatto solo di liste di customer in
sola lettura e capita spesso di trovarsi nella situazione in cui si
deve creare un nuovo customer e l'operazione di creazioni si svolge in
più di una richiesta http (pensiamo banalmente come esempio ad uno
wizard).

Diciamo che questa operazione deve essere fatta in session quindi alla
richiesta di creazione di un nuovo customer prendo la nuova istanza la
sbatto in sessione e li la aggiorno con i vari passaggi dello wizard e
solo alla fine salvo il tutto su db.

Qui nascono anche alcuni problemi di sviluppo, la sessione è molto
generica, alla fine è una hashtable fatta da una key di tipo string e
un object quindi il compilatore ti aiuta un gran poco e scrivere una
cosa del tipo:

Session["pippo"] = "ciao";
Int32 val = (Int32)Session["pippo"];

è facile come errore perchè non è typesafe, ergo scoppia a runtime e
non a compiletime il che è molto male...

Aggiungiamo poi una questione architetturale: la sessione è una cosa,
come dice il suo nome, che "spanna" tutto il ciclo di vita di un dato
utente nella nostra applicazione, mentre l'operazione di creazione di
un customer non dovrebbe spannare tutto il ciclo di vita dell'utente,
cioè è facile mettere il customer in sessione e poi anche dopo averlo
salvato dimenticarselo li...

Infatti i puristi definiscono l'operazione di creazione del cliente
"conversazione": la conversazione è quindi un'operazione che spanna più
richieste http ma non dura tutto il ciclo di vita della sessione, ci
possono essere più conversazioni in contemporanea.

Dopo averti annoiato con tutto ciò vediamo come tendo a procedere io,
partendo dal presupposto che la "sessione" (o qualcosa di paragonabile)
ci serve:

- la prima operazione che faccio è astrarre il concetto sia di Session,
che di Cache, che di HttpApplication: il tutto è abbastanza semplice e
si basa pesantemente sul concetto di Inversion of Control
(http://msdn.microsoft.com/en-us/library/aa973811.aspx), questo mi
porta a rapportarmi con un oggetto ICacheService (o ISessionService in
base al caso) che rappresenta le funzionalità desiderate ma maschera
l'implementazione reale.

Vediamo perchè questo sforzo (che non è poi sto gran sforzo):
Immaginiamo che tu stia costruendo un sito di ecommerce e che
giustamente abbia deciso che hai un set di dati che ha senso mettere in
cache perchè sono quasi sempre in sola lettura e anche quelle rare
volte che vengono scritti ti va bene che l’aggiornamente della cache
possa essere differito rispetto al momento della scrittura (è un
esempio).

Detto questo dopo un po' di tempo che sei in produzione ti ritrovi che
il sito di ecommerce ha avuto un successo strepitoso e la macchina su
cui sei ospitato non ce la fa più perchè il carico di utenti e
l'aumentare dei dati (ad esempio il set che metti in cache) stanno
saturando le risorse e si decide di spostare tutto su una farm in load
balancing per scalare orizzontalmente... boom non cambia nulla tutto va
in bomba lo stesso perchè la cache di asp.net non è condivisa tra le
macchine e ogni singola macchina della farm carica l'enorme set di dati
in cache. C'è una soluzione a tutto ciò? certo ad esempio distribuire
la cache sulle macchine della farm e far dialogare tra loro le macchine
come se fossero una rete neurale (non che sia facile, ma sicuramente è
affascinante da realizzare) se la tua applicazione fa uso di Inversion
of Control e non accede direttamente alla cache ma passa da un
ICacheService allora vedrai che è un gioco da ragazzi perchè il codice
dell'applicazione non lo devi neanche toccare.

La seconda operazione è quella di introdurre il concetto di
conversazione (IConversation) che mi serve per gestire il ciclo di vita
di quegli oggetti che sono temporaneamente in elaborazione. Anche qui
creo una semplice facade che inizialmente non fa altro che nascondere
allo sviluppatore che dietro c’è la session ma lascia aperte
innumerevoli strade.

Faccio un’ultima considerazione, pensiamo sempre alla session (o anche
a qualcosa che la mascheri, l’importante è il concetto di sessione) e
pensiamo al fatto che in tutti i casi hai di mezzo http quindi il fatto
che un utente non sia più connesso è sempre impossibile da rilevare e
quindi è necessario che i dati in sessione abbiano un timeout. In
quest’ottica ha decisamente senso pensare ad un sistema di persistenza
su storage fisico per alleggerire il carico sulle macchine, quindi il
concetto di sessione out of process su sql server è molto interessante
ma nell’implementazione di default come abbiamo visto è necessario che
tutto sia serializzabile e anche se auspicabile non è detto che sia
possibile ma se ci pensaimo bene a noi non interessa essere così
generici perchè se studiamo bene la nostra applicazione scopriamo che
in sessione ci mettiamo un set ben preciso e noto di cose quindi...
perchè non pensare di realizzare un motore di persistenza fatto ad hoc,
e quindi ottimizzato, per quel set di cose?

Tutte queste considerazioni sono, imho, sempre un must in caso di
applicazioni enterprise ma alcune possono essere un utile guida anche
per la quotidianità dello sviluppo, del resto realizzare una facade per
la session o per qualsiasi altra cosa una volta che hai capito i
concetti base è operazione decisamente rapida.

Sul mio blog ogni tanto divago e straparlo di queste cose ;-)

.m

--
Mauro Servienti
Microsoft MVP - Visual C# / MCP
http://mvp.support.microsoft.com
http://blogs.ugidotnet.org/topics
whynot [ at ] topics [ dot ] it


VeroToad [MVP]

da leggere,
6 giu 2008, 15:45:1106/06/08
a
Ciao Mauro Servienti [MVP],

[cut]


> mi intrometto... perchè il discorso mi sta molto a cuore

[cut]

Clap-clap-clap!
Ciao!

--
Simone Viganò AKA VeroToad - MVP Windows Desktop Experience
My blog: http://blogs.dotnethell.it/VeroToad
RIO (Risorse in italiano per utenti di Office): http://www.riolab.org


Rispondi a tutti
Rispondi all'autore
Inoltra
0 nuovi messaggi