Non-sticky sessions with Spring-Session (Part 1)

Preface:

I recently had to work on a project where we had to turn an existing Java (Springboot) application whom was served by multiple web servers sitting behind a load balancer and required sticky sessions to an application that could be deployed to an environment using non-sticky sessions.

The application was not stateless and was using the session to store data between requests.  After doing some analysis, changing the application to become stateless was not an option for us.  So we needed to save the session data somewhere, on disk, using Redis or a database.

Spring-Session

Spring-Session provided an API layer to persist session data without having to significantly change application code.  It basically provided an HttpSession implementation that saved data to disk and allowed application developers to continue freely using the Session object as before (as long as the data was serializable).

I won’t go into huge detail on how Spring-Session works, but it basically replaces the container provided HttpSession object with its own (via a Filter) and at some point, Spring-session will persist the data to someplace (as configured by us) without the application itself needing to know what is going on behind the scenes.

When the user’s request ends, the session data is persisted and when that same user makes another request, as expected, Spring-session will fetch the user’s session data and desearialize it.  The data will then be available using the HttpSession’s getParameter() methods as a conventional HttpSession object.

Proof of Concept and Session Store
Spring-Session comes with support using Redis as the session store (using Jedis).   So our first step in evaluating Spring-Session is to get a our application integrated with Spring-session,  setup a Redis and Redis backup (Redis slave) servers. This way we can determine if Redis is a good choice for our session store and if not, can we still use Spring-session with another session store (such as a relational DB).

One can argue if the redundancy of session data is actually required here.  That is, the data we are using Redis to store is only session data as the user navigates though our application and not actual user data that requires persistence.   I’ll leave that as a argument for a later time, but for our sake, we needed to see some redundancy features of Redis as a matter of “policy”.

Our PoC arcitecture looked like the following:

Setting Up With Maven
Spring-Session with Redis requires 2 dependencies,  i) the Spring-Session dependency and   ii) the Redis connector.   If you are are using a custom session store, you do not need to include the Spring-Session data-redis dependency.

  
      <dependency>
         <groupId>org.springframework.session</groupId>
         <artifactId>spring-session</artifactId>
         <version>1.0.2.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework.session</groupId>
         <artifactId>spring-session-data-redis</artifactId>
         <version>1.0.2.RELEASE</version>
         <type>pom</type>
      </dependency>

Springboot
If you are using Springboot, you have to create the JedisConnectionFactory bean that will be injected into the SessionRepositoryFilter.  Many of the configuration properties of a JedisConnectionFactory have default values, so the example below is pretty sparse.  I only specify the URL of my Redis master  instance, but it is in here where you can specify other properties such as password, etc.

  
    @Bean
    public JedisConnectionFactory connectionFactory() {
    	JedisConnectionFactory redisConnectionFactory= new JedisConnectionFactory();
        redisConnectionFactory.setHostName("redis.masterserver.com");
        redisConnectionFactory.afterPropertiesSet();
        return redisConnectionFactory;
    }

Testing the Setup
To test our Poc, we wanted to see that 1) our setup is truly session-sticky-less and 2) Redis data redundancy was working properly.

1) Session Stickiness
To test session non-stickiness, we send a HTTP request from a computer though the load balancer.   We find out it is being handled by application server A and the application puts some data into the session.  We then shut down server A and send another request from the same browser.  The request is now handled by server B, but because we’ve externally stored the session data, the user’s session (and data) are still alive.

2) Redis Redundancy
To test Redis redundancy, we sent a HTTP request to our app though the load balancer, but we don’t care which server handles the request.  We use the Redis client (redis-cli) check that the session data being stored in the master Redis instance.  We then connected the client to the slave instance and check that the same data is also in the slave.

 

Conclusion and More Work
It turned out that integrating our application with Spring-Session was very straight forward. Our PoC Redis and replication process was also easy to get going. A architectural decision was made on not to use Redis as the session store but we determined that we still wanted to use Spring-Session with a relational database as our storage. This leads us to part 2 of our Spring-Session introduction, using Spring-Session with a relational DB (Oracle or MySql).

References and other tutorials
If you are interested in more details on how to setup Spring-Session with Redis, you can look at these sites below. They helped us a lot.

  1. Spring-Session Project Page
  2. Video: Spring-Session by Josh Long
  3. Basic Tutorial
  4. Spring-Data: Jedis
  5. Managing Users Data with Spring Session
  6. Another Redis Replication Tutorial

 

One thought on “Non-sticky sessions with Spring-Session (Part 1)

  1. Pingback: Spring-Session with a relational database(Part 2) | my blog

Leave a Reply

Your email address will not be published. Required fields are marked *