When Jetty 7.5.0 is released we will have officially started to dabble in the area of distributed session handling and storage. To start this out we have created a set of abstract classes around the general concept of NoSQL support, and have prepared an initial implementation using MongoDB. We will also be working on Ehcache and perhaps Cassandra implementations over time to round out the offering, but it is overall a pretty exciting time for these sorts of things.
NoSQL sessions are a good idea for a number of usage scenarios, but as with NoSQL solutions in general, it is not a one-size-fits-all technology. The Jetty NoSQL session implementation should be good for scenarios that require decentralization, highly parallel work loads, and scalability, while also supporting session migration from one machine to the next for load balancing purposes. While we are initially releasing with just the MongoDB session manager, it is important to make clear that all the different distributed NoSQLish solutions out there have there own positives and negatives that you need to balance when choosing a storage medium. This is an interesting and diverse area of development, and since there is little standardization at the moment it is not a simple matter of exporting data from one system to the next if you want to change back ends.
Before jumping in and embracing this solution for your session management, ask yourself some questions:
- Do I require a lot of write behavior on my session objects?
When you’re dealing with anything that touches the network to perform an action, you have an entirely different set of issues than if you can keep all your logic on one machine. The hash session manager is the fastest solution for this use profile, but the JDBC session manager is not a bad solution if you need to operate with the network. That in mind, there is an optimization in the NoSQL session managers where tight write loops should queue up a bit before an actual write to the back end MongoDB server occurs. In general, if you have a session profile that involves a lot of writes all the time, you might want to shy away from this approach.
- Am I bouncing sessions across lots of machines all the time?
If you are, then you might be better off to get rid of sessions entirely and be more RESTful, but a networked session manager is going to be difficult to scale to this approach and be consistent. By consistent I mean writing data into your session on one node and having that same data present within a session on another node. If you’re looking at using MongoDB to increase the number of sessions you’re able to support, it is vitally important to remember that the network is not an inexhaustable resource, and keeping sessions localized is good practice, especially if you want consistent behavior. But if you want non-sticky sessions or mostly sticky sessions that can scale, this sort of NoSQL session manager is certainly an option, especially for lightweight, mostly read sessions.
- Do I want to scale to crazy amounts of sessions that are relatively small and largely contain write-once read-often data?
Great! Use this! You are the people we had in mind when we developed the distributed session handling.
On the topic of configuring the new session managers, it is much like other traditional ones: add them to the context.xml or set up with the regular jetty.xml route. There are, however, a couple of important options to keep in mind for the session ID manager.
- scavengeDelay–How often will a scavenge operation occur looking for sessions to invalidate?
- scavengePeriod–How much time after a scavenge has completed should you wait before doing it again?
- purge (Boolean)–Do you want to purge (delete) sessions that are invalid from the session store completely?
- purgeDelay–How often do you want to perform this purge operation?
- purgeInvalidAge–How old should an invalid session be before it is eligible to be purged?
- purgeValidAge–How old should a valid session be before it is eligible to be marked invalid and purged? Should this occur at all?
A guide for detailed configuration can be found on our wiki at on the Session Clustering with MongoDB page.
The new MongoDB session manager and session ID manager are located in the jetty-nosql module. Since we plan to have multiple offerings we have made the mongodb dependency optional, so if you’re planning to use embedded Jetty, make sure you declare a hard dependency in Maven. You can also download the mongodb jar file and place it into a lib/mongodb directory within the jetty distribution itself; then you must add mongodb to the OPTIONS on the cli or in the start.ini file you’re starting Jetty with.
There were a number of different ways to go in implementing session ID management. While we are wholly tolerant of a user request being moved from one server to another, we chose to keep normal session operations localized to the machine where the session originates. If the request bounces from one machine to another, the latest known session is loaded. If it is saved and then bounces back, Jetty notices the change in the version of the session and reloads, but these operations are heavy weight: they require pulling back all data of a session across the network, as opposed to a field or two of MongoDB goodness. One side effect of this approach is the scavenge operation executes only on the known session IDs of a given node. In this scenario, if your happy cluster of Jetty instances has a problem and one of them crashes (not our fault!), there is potential for previously valid session IDs to remain in your MongoDB session store, never to be seen again, but also never cleaned up. That is where purge comes in: the purge process can perform a passive sweep through the MongoDB cluster to delete really old, valid sessions. You can also delete the invalid sessions that are over a week old, or a month old, or whatever you like. If you have hoarding instincts, you can turn purge off (it’s true by default), and your MongoDB cluster will grow… and grow.
We have also added some additional JMX support to the MongoDB session manager. When you enable JMX, you can access all the normal session statistics, but you also have the option to force execution of the purge and scavenge operations on a single node, or purge fully, which executes the purge logic for everything in the MongoDB store. In this mode you can disable purge on your nodes and schedule the actions for when you are comfortable they will not cause issues on the network. For tips on configuring JMX support for jetty see our tutorial on JMX.
Lastly I’ll just mention that MongoDB is really a treat to work with. I love how easy it is to print the data being returned from MongoDB, and it’s in happy JSON. It has a rich query language that allowed us to easily craft queries for the exact information we were looking for, reducing the footprint on the network the session work imposes.