Offload HTTP Sessions with Spring Session and Redis

Context

Applications running in Cloud Foundry should offload the sessions to a Redis service. The applications should be stateless in nature, and any crash of the an application instance, should not impact the other application instances and user workflows.

Configure the service and bind to the application

By default, the Tomcat instance is configured to store all Sessions and their data in memory. Under certain circumstances it my be appropriate to persist the Sessions and their data to a repository. When this is the case (small amounts of data that should survive the failure of any individual instance), the buildpack can automatically configure Tomcat to do so by binding an appropriate service.

The PCF GO Router uses the jsessionid plus a vcap_id to establish sticky sessions. Session replication breaks with sticky sessions at the GO router which is one of the reasons Spring Session is used. By default Spring Session creates a custom SESSION cookie to house the applications HTTP session.

See: https://docs.pivotal.io/pivotalcf/concepts/http-routing.html Note: CF does not persist or replicate HTTP session data across app instances. If an app instance crashes or is stopped, session data for that instance is lost. If you require session data to persist across crashed or stopped instances, or to be shared by all instances of an app, store session data in a CF marketplace service that offers data persistence.

Prerequisites

  1. ENSURE YOUR SESSION OBJECT IMPLEMENTS SERIALIZABLE

NOTE: This recipe was customized for Spring 3.2.18 and XML Configuration. It is highly recommend to bootify your application and leverage the Spring Boot Starter modules to help stay current with Spring versions.

PCF and Redis Service Creation

To enable Redis-based session replication, simply bind a Redis service containing a name, label, or tag that has session-replication as a substring.

NOTE: After initial setup and testing of the redis session functionality, it is recommended to add your service binding to the PCF manifest.yml file.

> cf create-service p-redis <plan-name> session-replication

> cf bind-service <app-name> session-replication

> cf restage <app-name>

Manual Definition for session replication with Redis

Since the code uses the Tomcat HTTPSession, we need to update to SpringSession as SpringSession can handle the objects marshalling/unmarshalling better than Tomcat HttpSession, we need to add the following dependencies in our web modules.

NOTE: USE SPRING SESSION from the beginning of your session replication adventure. CF has built-in session managament capabilities but it has limitations. ]

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

Define the session configuration in your web.xml

NOTE: For the session replication to work with spring security, you need to place the spring session filter above spring security filter.

NOTE: For the session replication to work with struts, you need to place the spring session filter above the struts filter.

  <filter>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>ERROR</dispatcher>
  </filter-mapping>

Define the following in your Spring application-context.xml:

  ...
  <context:annotation-config/>
  <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
  <bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" />
  <util:constant static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>
Contact Us