Software Develoment Journey
Java, Spring Framework, How-to

Solving REST + Spring Security session problem

REST, sessions .. wait. There are no sessions in REST application, right? Well, thats true. If we can avoid sessions we should do that. REST is stateless. The main concern about statelessness is authentication. In usual web applications we were used to store user data in session after authentication. How to solve that if we don’t want to use sessions? We should authenticate every request.

Thanks to that we can scale our application, add new nodes, remove nodes without care about session replication and also about consumed Java heap memory.

Recently I’ve been working on high load REST application. Actually we didn’t expect to have high traffic there but surprisingly we had much much higher that we have been prepared for (it’s so called “happy problem”). Application is based on Spring Framework and its secured with Spring Security deployed on Apache Tomcat 7. All resources are totally stateless – HttpSession is not touched by any piece of my code. Unfortunately used Java heap space was increasing all the time until:

java.lang.OutOfMemoryError: Java heap space

was thrown. In order to analyze Java heap dump and runtime usage of heap I used VisualVM.

 

Heap dump analysis shown that big part of memory was used by ConcurrentHashMaps used by Tomcat to store sessions. Those sessions object were almost empty but there were so many of them that they consumed ~50% of reserved Java heap space.

 

Add parameter to Tomcat startup script: -XX:+HeapDumpOnOutOfMemoryError to get Java heap dump on java.lang.OutOfMemoryError: Java heap space

First thing that I’ve done was to limit session timeout from default 30 minutes to 1 minute (lowest possible option) in web.xml:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
    <!-- ... -->

    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>
</web-app>

That solved the problem – heap was cleaned by GC with better results and OutOfMemoryError was not thrown anymore. But more important thing is where those sessions were coming from? The answer is: Spring Security.

By default Spring Security creates sessions if required – which means that if user has authenticated successfully then session is created. In my case it meaan – always. In order to prevent Spring Security from creating sessions create-session="never" needs to be added to http:

1
2
3
<http create-session="never">
    <!-- ... -->
</http>

You might think – empty session objects should not be a problem. I can tell you that for application handling few hundreds of requests per second it does a real change. Especially when its not running in the cloud or has few GB or RAM memory dedicated for Java heap. That’s how Java heap usage look like after those modifications:

 

If you enjoyed this post, then make sure you subscribe to my RSS feed