Sticky Sessions refers to the need to redirect the requests of a given user to the same server where his session lives in. It is considered an anti-pattern as in case of a server failure, all users connected to it will lose their sessions.

The association between the user and the server is usually configured via Load Balancer, and simple load balancing strategies like Roundrobin are often not enough to ensure an even distribution of the requests, as heavy users might end up all in the same node. There are many ways in which sticky sessions could be avoided, but if your application stores user’s data in the  HTTPSession, the options without requiring a substantial refactoring are a little bit limited.

One quick fix to this problem is to store the session in the database instead of using the server’s memory. In this scenario, no matter what node receives the request, it will load the user’s session directly from the data store. This approach is simpler than container specific solutions, and also allow you to query sessions like anything else in your database.

Couchbase fits particularly well in this scenario: It uses the internal key-value engine and also leverages the internal cache layer to keep the recently used sessions in memory. In practice, it means that this is a solution that will perform well even at scale. That is why we are adding community support Spring Session:

Couchbase Spring Session makes it trivial to support clustered sessions by storing it on the database and from the developer point of view it is totally transparent. All you have to do is to add the following dependency:

and then, in your main class, add the @EnableCouchbaseHttpSession annotation:

and that is it!. Spring will automatically save the HTTPSession in the Couchbase from now on:

By default, the session will be stored in the database in a document with a type equals to “sessions“:

But you can change the name of the type attribute, the type value and how long the session should last:

 

Querying the user’s session

Note that, all session’s data is binary stored in an attribute called _attr:

Spring doesn’t know which objects types are in the session, so there is no easy way to convert it to human-readable format. You can overcome this limitation by setting the attribute keepStringAsLiteral as true in the EnableCouchbaseHttpSession annotation:

keepStringAsLiteral will tell Couchbase Spring Session to store all session’s String attributes as top-level properties within the document. For instance, instead of adding an instance directly to the session, we could convert the object to a JSON-encoded String format using Jackson’s ObjectMapper:

And then, when you need to read the session cart, convert it back to an object:

This will add a small extra effort when you need to add/remove/update data from the session, but on the flip side, you will able to query sessions. Here is how the document will look like in the database:

Note that we still have the _att attribute for objects which are not a String. However, now we also have an attribute called key, which is exactly the object we added to the session in the previous example.

Now, if you want to query your session, N1QL has a function called DECODE_JSON, which can unmarshal a JSON-encoded String to an object:

Note: In a production environment, we recommend you to create an index with the decoded object instead of decoding it on query time.

If you want to read more about Couchbase Spring Session, check out this tutorial

If you have any questions, feel free to pint me at @deniswrosa

Posted by Denis Rosa, Developer Advocate, Couchbase

Denis Rosa is a Developer Advocate for Couchbase and lives in Munich - Germany. He has a solid experience as a software engineer and speaks fluently Java, Python, Scala and Javascript. Denis likes to write about search, Big Data, AI, Microservices and everything else that would help developers to make a beautiful, faster, stable and scalable app.

Leave a reply