Clustered Environment and Session Management (Servlets) - servlets

I was reading a book on Java Servlets where I came across HTTPSessionActivationListener. It was specified that in a clustered environment , there can be only one HTTPSession object containing a specific session id. Assume there are 2 nodes A and B in a cluster -
first request goes to node A. Here a HTTPSession S1 is created along with session attributes and response goes back to the client.
Same client sends the subsequent request. This request goes to node B. Now the session object S1 is moved from node A to node B (activated in Node B and passivated in node A).
In this case should the session object along with the attributes be serializable? What happens if it is not serializable?
In order to count the number of active sessions , should the sessions in both nodes be added up to get the actual value? How is this usually done?
Also I guess ServletContext is unique for each JVM. Are the attributes set as part of servletcontext copied to servlet context in all nodes of the cluster?

Usually I've seen people use sticky sessions (provided usually by the load balancer, for example ec2 ELB has this feature: http://shlomoswidler.com/2010/04/elastic-load-balancing-with-sticky-sessions.html), OR the session data is stored in a shared repository, such as a database or NoSQL store.

Spring session seems to be offering a capability called 'Clustered Sessions' and it also has feature to offload the session to a RedIs or GemFire caching solution.
Reference: http://projects.spring.io/spring-session/

Using a caching solution like Infinispan, hazelcast or redis would be the way to go if you want sessions to survive server failure. Application servers provide these function integrated now a days. You can just enable them from admin interface for web/ejb/jms persistance. If you are storing something into session in your code, you can use JCache API to store them on the underlying cache. JCache provides a product independent caching API, makes you code portable across caching solutions.

Related

Session Consistency and the .NET Client SDK

I am trying to understand what Sessions Consistency actually means when working with Azure DocumentDb via the .NET client SDK i.e. What defines (and bounds) a session. Is a new session created each time we create a new instance of DocumentClient and if so does the behavior change if we are using the IReliableReadWriteDocumentClient wrapper?
Yes, a new session is created each time you create a new instance of the DocumentClient class. Each DocumentClient instance maintains a map of collection -> session token mapping. The client saves the latest session token received from the server, and echoes it as a header (x-ms-sessiontoken) during read requests. This enables DocumentDB to locate an up-to-date replica of your collection to serve session (or read-your-writes) consistency. This is the same with IReliableReadWriteDocumentClient, since it's a wrapper over the DocumentClient.
Note: the easiest way to achieve session consistency is to have a single DocumentClient instance manage it for you automatically. You can also manage a logical session across multiple DocumentClient instances with a little more complexity. For example, let's say that you have a load balanced Web API with two servers each with a DocumentClient instance, and you want session consistency across these servers.
client writes -> App Server 1 -> DocumentDB
client reads -> App Server 2 -> DocumentDB
You can implement this by saving the x-ms-sessiontoken returned in step 1 by saving it as a cookie in the client, then echoing that x-ms-sessiontoken in the read request. By round-tripping the session token, you can get session consistency.

Session state access in Web API across domains

I have a ASP.Net API implementation, where to store and access the data / variables across consecutive calls, I am using a session state object as shown below and it can be successfully accessed in the multiple calls to separate calls by a browser:
// Access the current session object
var blSession = HttpContext.Current.Session;
// create the BL object using the user id
BL accessBL = new BL(userID);
// Store the Bl object in the session object dictionary
blSession["UserBL"] = accessBL;
I have to enable the following setting in the Global.asax, for the Session object to be accessible:
protected void Application_PostAuthorizeRequest()
{
// Enable session state in the web api post authorization
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
Issue comes in when the WebAPI shown above has to be accessed via another ASP.Net MVC client, which is separately hosted on a different machine, at that time same consecutive calls do not maintain the state as shown above and thus it leads to an exception, since the consecutive calls rely on session data to proceed.
I have seen a similar issue when I seen the similar issue when I use the Fiddler Debugger, as it gets hosted as a web proxy, so consecutive calls through that too fails, since it does not maintain the state. In my understanding, issue is due to setting the Cookie across domain, which doesn't seem to work across domains due to security reason
I know a workaround is to use an application wide variable like Cache, but please suggest if you have a way to get the SessionState work. Let me know if you need more details.
If you have not setup an alternative way to do SessionState, then the default behavior is to do it InMemory on the server. This is why you are seeing issues when the request is handled by a different ASP.NET server.
Web API calls are meant to be stateless. That is, they should not perform like a classic ASP.NET application that relies on the framework to store user specific information in Session variables across HTTP requests. For each call, pass in a user-specific identifier or token that you can then use to lookup information stored in your backend. You can store this information in your database or a distributed cache like MemCache for faster retrieval.

ASP.NET Session State in Cluster

Our project was implemented originally with in memory session state. We need to scale up and add another server in an IIS server farm. I did all the steps to get the session state stored in a sql server database, but not all my objects are serializable, and db session state does require serializable objects.
My current thought is to create another layer of structs to mirror all the data that need to be serializable, and store them in session. When I need access to my object, I would use an adapter to morph the session struct into the object I need. Is this the way to go, or are there better options (other than manually making sure my current classes are serializable)?
The Load Balancer of the farm should be configured to serve all requests of a client to the same server.

HttpSession Session ID different to FlexSession ID

I have a Flex application which is served via a JSP page. In this page I output the session ID using HttpSession when the page is loaded:
System.out.println("Session ID: " + session.getId());
In a very simple remote object hosted in BlazeDS (called from the flex application using an AMF Channel and standard RemoteObject functionality) I also output the session ID but this time using FlexSession (which as I understand is supposed to wrap around HttpSession).
System.out.println("FlexSession ID: " + FlexContext.getFlexSession().getId());
I would expect both IDs to be the same but this is not the case. The session IDs differ which is causing problems as there is data stored in the HttpSession which I need to be able to access from my remote objects within BlazeDS.
I've exhausted the reading material on BlazeDS and FlexClient/FlexSession/FlexContext but can't see why the FlexSession is not being linked to the HttpSession. Any pointers greatly appreciated.
I feel I must be missing something fundemental here, am I accessing the
I do not think that it is related to the FlashPlayer..is more related to the concept of FlexSession and how BlazeDS/LCDS works. For example you can have an active session even when not using the http channels - when using NIO/RTMP you are bypassing the application server and the http protocol. So it make sense to have an abstract class FlexSession with various implementations.
However when using BlazeDS FlexSession will wrap an HttpSession object internally, and removeAttribute/getAttribute/setAttribute are in fact calling the the same methods from the HttpSession object..so you can access all the data from the HttpSession. If not please provide more details.
However, it will not work when using RTMP channels(which exists only in LCDS by the way), you need to change your design in this case.
Thanks to both answers above I finally found the root cause and thought I'd share it on here.
The reason for differing session IDs was to do with the use of SSL for authentication and the use of AMF Channel rather than Secure AMF. Using the channel for the first time caused a new session to be created (hence the different ID) as the existing session related to the secure version of the site.
Silly configuration mistake but worth passing on - make sure that if using SSL that you're also using Secure AMF connecting to the secure endpoint rather than standard AMF or you'll run into the same session ID problems I faced.
Unfortunately this is just how the Flash player works. I have seen this same behavior many times.
The best solution I found was to establish the HTTP session and pass back the session ID. On the client side, you can then pass the session ID to the Flex application. You then send that ID from Flash to the server and use it to look up the existing session or establish a second session.
You will need to do something like this though, I have not been able to find a way to reliably get Flash to use the same session.

Object integrity and caching in a stateful client

I'm wondering what strategies exist to handle object integrity in a stateful client like a Flex or Silverlight app.
What I mean is the following: consider an application where you have a Group and a Member entity. Groups contain multiple members and members can belong to multiple groups. A view lists the different groups, which are lazy loaded (no members initially). When requesting the details of the group, all members are loaded and cached so the next time we don"t need to invoke a service to fetch the details and members of the group.
Now, when we request the details of another group that has the same member of a group that was already loaded, would we care about the fact that the member is already in memory?
If we don't, I can see a potential data conflict when we edit the member (referenced in the first group) and changes are not applied to the other member instance. So to solve this, we could check the result of the service call (that gets the group details) for members that are already loaded and then replace the loaded ones with the cached ones.
Any tips, ideas or experiences to share?
What you are describing is something that is usually solved by a "first-level cache" (in Hibernate, the "Session"; in JPA, the "EntityManager") which ensures that only one instance of a particular entity exists in a particular context. As you suggest, this could be applied to objects as they are fetched from the server to ensure that all references to a particular entity are in fact references to the same object instance. You would also need a mechanism to ensure that entities created inside the AVM exist in that same context so they have similar logic applied to them.
The Granite Data Services project has a project called "Tide" which aims to solve this problem:
http://www.graniteds.org/confluence/display/DOC/6.+Tide+Data+Framework
As far as DDD goes, it's important not to design the backend as a simple data access API, such as simply exposing a set of DAOs or Repositories. The client application cannot be trusted and in fact is very easy to manipulate with a debugging proxy such as Charles. I always design a services API that is tailored to the UI (so that data for a screen can be fetched in a single call) and has necessary security or validation logic enforced, often using annotations and Spring AOP.
What I would do is create a client side application service which does the caching and servicing of requests for data. This would handle whether an object already exists in the cache. If you are using DDD then you'll need to decide what is going to be your aggregate root entity. Group or Member. You can't have both control each other. There needs to be one point for managing loading etc. Check out this video on DDD at the Canadian ALT.NET OpenSpaces. http://altnetpedia.com/Calgary200808.ashx

Resources