Variables Websession en cluster con balanceo de carga

Me tocó instalar una aplicación GeneXus web, que utiliza variables websession en un cluster con NLB (varios servidores con balanceo de carga entre ellos.

La aplicación hacia un Login guardando información de si el usuario estaba conectado o no en una websession.

Cuando la aplicación era instalado en un servidor único, funcionaba correctamente. Cuando la persona se conectaba, podía hacer varias operaciones manteniendo la sesión. Si no tenia actividad por 20 minutos, desconectaba al usuario (el tiempo es configurable).

El problema que se daba cuando funcionaba en el cluster, era que el usuario se conectaba y se desconectaba todo el tiempo, sin un patrón muy claro. Busque en el WEBSAC y no encontré nada.

Como por defecto las aplicaciones ASP.NET guardan las websession en la memoria del working process del IIS. Como en esta aplicación pueden haber mas de un working process, se pierden las sesiones y por lo tanto el usuario ve como se desconecta la aplicación.

La información de la sesión, pueden almacenarse en :

  • la memoria del working process (InProc - esto es por defecto)
  • ASP.NET State Service (es un servicio que hay que configurar)
  • SQL Server 2000 o superior. 

Decidimos utilizar la ultima opcion, almacenando la sesion en SQL Server. Suponiendo que se utiliza el .NET Framework 2.0, hay que hacer:



1) Correr el script que esta en C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallSQLState.sql 
 Esto lo que hace es crear una base que se llama aspstate y stored procedures. 

2) Cambiar el web.config de la aplicacion  y agregar (tiene espacios de mas).

<system.web>
<trace enabled="false" />
<httpHandlers>
<add verb="*" path="*.aspx" type="GeneXus.HttpHandlerFactory.HandlerFactory,gxclasses" />
httpHandlers>
<sessionState mode="SQLServer" allowCustomSqlDatabase="true" sqlConnectionString="ASPNETConnString" />
system.web>
<connectionStrings>
<add connectionString="Server=NombreServidorSQL;Database=aspstate;User ID=Usuario;Password=Clave" name="ASPNETConnString" />
connectionStrings>

  < system.web >
    < trace enabled="false" / >
    < httpHandlers>
      < add verb="*" path="*.aspx" type="GeneXus.HttpHandlerFactory.HandlerFactory,gxclasses" / >
    < /httpHandlers >
    < sessionState mode="SQLServer" allowCustomSqlDatabase="true" sqlConnectionString="ASPNETConnString" / >
  < /system.web >
 < connectionStrings>
    < add connectionString="Server=NombreServidorSQL;Database=aspstate;User ID=Usuario;Password=Clave" name="ASPNETConnString" / >
  < /connectionStrings >

3) Ajustar los valores de usuario y contraseña para que se pueda conectar. 

4) Chequear que el servicio SQLAgent este corriendo, pues es el que mata las sesiones cuando pasan el tiempo configurado para las sesiones. 

Algunos links que pueden ser útiles 


Comentarios

  1. Ojo, una cosa es cómo maneja el balanceador las sesiones y otra es como IIS lo hace.

    Te recomiendo que veas por el lado del balanceador las opciones que tienes antes de usar la statefull por SQLServer, ya que ésta última en caso de que tu aplicación tenga una carga muy alta de usuarios no es la más indicada. (hay que ver si tienen balanceador por disponibilidad, o tienen balanceador por alta carga, depende el caso).

    ResponderEliminar
  2. Enrique, eso es lo que estamos haciendo para hacer deploy de aplicaciones a Windows Azure. Donde todo funciona perfectamente si tienes una instancia pero si levnatas mas te empiezas a encontrar con el problema de la sesión (entre otros)

    ResponderEliminar
  3. David/Sebastian:
    Gracias por los comentarios. Me llama la atención que tengamos tan poca documentación sobre el problema, pues parece algo bastante común, sin embargo no encontré nada.

    ResponderEliminar
  4. Enrique, es cierto que hay poca información, o por lo menos no es que exista poca, sino que no está bien correlacionada con las diferentes soluciones (El balanceador te dice, A,B o C, pero nadie te dice que A es bueno para el caso X del producto Z o C para el Y).

    Para el caso de Azure por ejemplo (me imagino que es lo que comenta Seba), la gente de Microsoft recomienda el uso de un proveedor de sesiones propio, que lo que hace es almacenar las sesiones en su propio sistema de almacenamiento (en el siguiente ejemplo muestran cómo, lo increíble es que puedes buscar por internet sobre el tema y mucha gente anda buscando esa info sin que exista un lugar con la info concreta de cual es la mejor practica http://blogs.msdn.com/b/jnak/archive/2009/11/19/using-the-sample-windows-azure-asp-net-providers.aspx)

    Si necesitas info sobre la configuración del balanceador de carga, pasame cual están utilizando y veo de pasarte la info que pueda conseguir.

    Lo otro interesante es que en internet hay mucho ejemplo simple y documentación rebuscada, pero hay pocos sitios en donde se documenten las buenas prácticas o las cosas que funcionan, y mucho menos orientado a la comunidad GX que comparada a las otras es mucho mas chica (y menos cuando hablamos de alta disponibilidad, escalabilidad, etc).

    Arriba Enrique, me encanta que hagas este tipo de aportes, muchos de la comunidad seguramente no conocen a fondo el manejo de sesiones, y por ejemplo, algo que no mencionas en tu blog, es que si usas este método (out process o en sqlserver) tienes el beneficio de que el usuario no se entera cuando existe un reciclado de la aplicación, el mismo no pierde nunca la sesión mientras esos eventos ocurran.

    ResponderEliminar
  5. Podrías retroalimentarnos de la charla interna de GXTest del grupo de desarrollo ;)

    jeje pa sacarle provecho nomás

    ResponderEliminar
  6. ** Esto me llego por mail, pero lo publico pues creo que aporta (Enrique) ***

    Nosotros no optamos por usar SQL Server como servidor de sesiones.
    El tema en torno a tu problema está en cómo configuraron el servidor de sesiones.

    Lo que se hace generalmente es indicarle al balanceador que utilice Sticky Session o con Afinidad (Affinity)

    Lo que te sucedía es que tu balanceador estaba configurado para un tipo de Appserver de tipo de páginas estáticas sin sesión. Es lo mejor, a medida que hay peticiones se balancea entre ellos de forma dinámica, por lo que en un momento estás en uno y en otro momento te pasó a otro y perdiste la sesión.

    Si tienes afinidad, al momento de la primer conexión, se te asigna unservidor en base a la carga que tenga, por lo tanto a medida que ellos se conectan van siendo balanceados.
    Luego, si uno de esos servidores falla, solamente los que estaban ligado son los que pierden la conexión.

    En nuestra aplicacion donde tenemos en ocasiones miles de usuarios conectados.. funciona y es la mejor opción (mismo para la lógica del balanceador).

    Usar sesiones por SQLServer es recomendado solo si usas muy poco la información almacenada en las sesione y si no tienes mucha carga.
    Nosotros lo manejamos “in Process” para que sea lo más performante posible y como corre a nivel de cada servidor no hay perdido de tiempos de comunicación contra otros (ir out Processo SQL SErver)

    Te recomiendo después con tiempo entrarle a mirar, si es un balanceador de Microsoft seguramente se encuentre relacionado con el concepto de Afinidad, pueden encontrarlo en otros como Sticky (Pegajoso)

    ResponderEliminar
  7. ¿Quien fue el del post?

    "Podrías retroalimentarnos de la charla interna de GXTest del grupo de desarrollo ;)"

    Me perdí, no entendí la propuesta :P ¿que tiene que ver GXTest en todo esto?

    Fui yo el del mail (no se porque Enrique no quiso mencionarme :P), Sorry comunidad, no quise postear un mega comentario (ya me han dado palo antes por eso). Amerita ver de crear algo en la Wiki de Artech al respecto (gente el aporte lo haga gente con experiencia y que conozca a fondo el tema, yo toco de oido)

    D+ que lo publiques, claro que aporta. :)
    En lo que pueda ayudar me encuentro a las órdenes (en este tema estoy con perfil "opinador", poseo parte del conocimiento y la experiencia pero nunca toqué yo un balanceador de carga).

    ResponderEliminar
  8. David: Creo que lo de gxtest, es en respuesta a un tweet mio (http://twitter.com/ealmeida/status/21493893815) de una charla que tuvimos en un grupo de desarrollo de Concepto, para explicar el nuevo proceso de testeo con GXTest que estamos implementando.
    Como decis, no tiene nada que ver con este post y no tengo a quien contestarle por lo que la voy a dejar por ahi.

    ResponderEliminar
  9. Solo quiero agregar una cosa... no siempre tenemos la opción de manejar temas de infraestructura y posiblemente (y personalmente espero que así sea) cada vez necesitemos menos conf de hardware. La virtualización (creo yo) nos va a llevar a un escenario donde tenemos que asegurar que nuestra aplicación corra independientemente de su entorno (con ciertos límites obviamente)

    ResponderEliminar
  10. Uyyyy no tengo twitter por eso dejé el comment acá...que suceptibles!!!!!!

    ResponderEliminar
  11. Enrique, muy bueno el artículo, siempre aportando cosas poco accesibles, pero necesarios.
    Vimos este post buscando una solución para borrar credenciales de un servidor con una aplicación .net externa. ¿Tedrás idea de cómo podemos eliminar las credenciales del IIS "a mano"?, si es así te agradecería mucho que me contactes.

    ResponderEliminar
  12. Guillermo:
    No me queda claro que es lo que estas buscando.
    Si te refieres a destruir la websession, haciendo que la sesion figure como desconectada, podes hacer:

    &WebSession.Destroy()

    y con eso se destruye el contenido de la websession.

    Si no es es lo que buscas, por favor aclaralo y le buscamos la vuelta.

    PD: Me gusto tu comentario que dice "siempre aportando cosas poco accesibles, pero necesarios"

    ResponderEliminar
  13. Gracias Enrique por responder!

    Te cuento que hacer un destroy de la websession no elimina las credencias, si el IIS las solicita en lugar de usar una conexión anónima.
    El tema es que no encontramos cómo eliminar estas credenciales una vez ingresadas, para que otro usuario utilice la aplicación sin necesidad de cerrar el browser (cosa que sí elimina las credenciales)

    Espero que se entienda la necesidad.

    ResponderEliminar

Publicar un comentario

1) Lee el post
2) Poné tu opinión sobre el mismo.
Todos los comentarios serán leidos y la mayoría son publicados.

Entradas más populares de este blog

El Sordo

StackOverflow Documentation

Codigo simple