In my first article on taking advantage of RabbitMQ's asynchronous messaging to implement a cloud-friendly session manager, I covered the method behind the madness and introduced you to some of the functions a session manager has to perform in the course of doing its job. In this, the second of two articles covering this topic, I'll describe how loading and updating session objects is handled and, in the interest of fairness, give some disclaimers and acknowledge the trade-offs made to get here.
The Code (at 1,000 feet) cont'd
Whenever code wants to interact with a user session, whether that be to load it into its own memory or to replicate attributes on that session, it sends these messages to a queue whose name contains the session ID. The pattern used to create the queue name is configurable so you can partition user sessions by application, or even by something more fine-grained (without resorting to using multiple, non-clustered RabbitMQ servers).
The session store first checks its internal Map to see if the requested session happens to be local to this store. If it is, the store simply hands that session back to the manager. If it's not, then the store sends a "load" message to the session's queue. It doesn't just fire off a message, though. It turns out that a user's session can be requested from the store many times during the course of a request. If one were to send a load message every time this happens, then we would see a serious performance degradation. To get around this, before a load message is sent, the store checks to see if it's already trying to load this session. If it is, it simply waits until that process is finished and uses the session being loaded in that other thread.