[ASP.NET] Sistema realtime di rilevamento degli utenti connessi
Conoscere il numero preciso di utenti connessi in un’applicazione ASP.NET non è possibile, sfruttando ad esempio le Membership API è possibile ottenere il numero di utenti connessi usando come criterio discriminante il timeout della Session (Membership.GetNumberOfUsersOnline()). In questo modo però è possibile monitorare solamente gli utenti loggati e comunque il numero rimane piuttosto approssimato.

Personalmente non ho mai avuto la necessità di tenere una traccia più accurata a scopo statistico, ma vediamo comunque come risolvere il problema :-).

Ah, il famigerato evento Session.End *non* è deterministico, quindi non lo si può sfruttare per questo obiettivo.

La soluzione è piuttosto semplice:
- un WebService che i client chiamano ciclicamente
- un timer Javascript che richiama il WebService 
Web server structure


1) L’attributo ScriptService permette di chiamare il web service tramite AJAX.
[WebService(Namespace = "http://eyeopen.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
[ScriptService]
public class AliveService : WebService
{
    [WebMethod]
    public void SendAlive()
    {
        ////string sessionId = HttpContext.Current.Request.Params["ASP.NET_SessionId"];
        string sessionId = HttpContext.Current.Request.UserHostAddress;
        UsersManager.RegisterUser(sessionId);
   }
}

2) Il file Javascript necessario a chiamare il web service:

function SendAlive() {
    EyeOpen.UsersMonitor.Web.AliveService.SendAlive();
}

function AliveTimerTick() {
    SendAlive();
    setTimeout(AliveTimerTick, 1000);
}

if (typeof (Sys) !== "undefined") {
    Sys.Application.notifyScriptLoaded();
}

setTimeout(AliveTimerTick, 1000);

 


3) Infine la reference al file Javascript tramite lo ScriptManager
e la reference al web service:

<asp:ScriptManager ID="scriptManager" runat="server">
    <Scripts>
        <asp:ScriptReference Path="~/Js/Alive.js" />
    </Scripts>
    <Services>
        <asp:ServiceReference Path="~/Core/AliveService.asmx" />
    </Services>
</asp:ScriptManager

 


La rappresentazione della classe di supporto al web service: 
Classe di supporto al web service

In sostanza il web service lato server viene chiamato da un timer javascript ogni secondo, con un basso carico di rete e sul server, segnalando la presenza dell’utente, nel momento in cui vengono chiuse tutte le pagine che richiamano il servizio entro 10 secondi (il tempo di timeout si gestisce tramite web.config) l’utente viene cancellato dalla lista degli utenti connessi.

E’ sufficiente inserire lo ScriptManager in tutte le pagine (ad esempio tramite MasterPage o da codice) e il sistema viene esteso a tutta l’applicazione web.

Qui si trova il progetto di esempio: EyeOpen.UsersMonitor.Web.

Matteo Migliore.
7 Comments Filed Under [ ASP.NET ]

Comments

# re: [ASP.NET] Sistema realtime di rilevamento degli utenti connessi
Gravatar Invia di una richiesta ogni secondo da tutti i client? Carico assurdo al server!

La verità la dici anche tu ;)

"Personalmente non ho mai avuto la necessità di tenere una traccia più accurata a scopo statistico..."

E poi tale tecnica ha il problema di non prendere in considerazioni client con javascript disabilitato.

Ciao
Left by Claudio on 07/07/2008 8.36
# re: [ASP.NET] Sistema realtime di rilevamento degli utenti connessi
Gravatar Scusa, le osservazioni che hai scritto le ho già fatte. Cos'hai aggiunto?

Se javascript è disabilitato i problemi sono molti altri!

In ogni caso la frequenza lato client si può impostare più bassa, dipende dalla precisione che si vuole ottenere e dal numero di utenti. Comunque il carico è molto basso.

Matteo Migliore.
Left by Matteo Migliore on 07/07/2008 10.38
# re: [ASP.NET] Sistema realtime di rilevamento degli utenti connessi
Gravatar Cosa aggiungo? Tu affermi: "In sostanza il web service lato server viene chiamato da un timer javascript ogni secondo, con un basso carico di rete e sul server". Tu lo ritieni un basso carico di rete? Ipotizza 100, 1000 utenti online contemporaneamente e poi rivaluta il carico e i benefici.

Claudio
Left by Claudio on 08/07/2008 8.11
# re: [ASP.NET] Sistema realtime di rilevamento degli utenti connessi
Gravatar Io ritengo la tua soluzione più che accettabile.
A cosa può servire.....
ipotizziamo che io abbia venduto al cliente un numero preciso di licenze. Devo controllare quanti utenti sono collegati simultaneamente con una precisione molto alta.

Grazie Matteo
Gianni
Left by Gianni on 08/07/2008 9.34
# re: [ASP.NET] Sistema realtime di rilevamento degli utenti connessi
Gravatar @Claudio: si può abbassare la frequenza con cui i client chiamano il servizio. Non ho tempo di fare test di carico sulla banda, perchè è l'unica cosa ad essere consumata, CPU e RAM sono praticamente ininfluenti. Quindi anche con 100.000 utenti (ho lavorato su applicazioni con questo carico) il lavoro sarebbe minimo, e si può comunque scalare su altri web server nel caso in cui la feature richiesta sia indispensabile.

Matteo Migliore.
Left by Matteo Migliore on 08/07/2008 10.45
# re: [ASP.NET] Sistema realtime di rilevamento degli utenti connessi
Gravatar Bellessimo articolo!! Mi serviva proprio.

Ma ho una domanda:
come mai usi un javascript per chiamare il servizio web e non un Timer sulla MasterPage?
Vedo che poi lo usi per aggiornare la lable contatore sulla pagina.

Si potevano usare 2 Timer o come hai proposto SOLO un javascript?

GRAZIE
Massimo
Left by Masimo on 27/08/2008 9.36
# re: [ASP.NET] Sistema realtime di rilevamento degli utenti connessi
Gravatar complimenti per l'articolo, davvero interessante.

Nella mia applicaizone però non posso usare il framework. 3.5 e di conseguenza linq.
Cone posso adattare la senguente funzione?


private static void UpdateOnlineUsers()
{
DateTime now = DateTime.Now;

List<string> offlineUsers =
(from user in GetOnlineUsers()
where now.Subtract(user.Value).TotalSeconds > UserOfflineTimeout
select user.Key).ToList();

offlineUsers.ForEach(userId => GetOnlineUsers().Remove(userId));
}
Left by ale on 22/09/2008 12.34

Leave Your Comment

Title*
Name*
Email (never displayed)
 (will show your gravatar)
Url
Comment*

Please add 5 and 2 and type the answer here:

Preview Your Comment.