Java Servlet HttpSessions are deceptively cool.  They allow you to store away stuff for a user and they have a lifecycle that cleans up after themselves.

Buy they do have a cost.  If you instance is open to the wider web, the sessions can chew up memory and hence if there are 1000s of sessions it can be chewing up heaps of memory.

Sessions are also an inhibitor to producing web scale applications because of the cost and difficulty of “synchronising” the state between multiple servers.  But that’s not the point of this post.

JIRA standalone moved to a much longer session life by default (5 hours up from 1 hour) and hence more session memory can be used for much longer than before.

A recent examination of https://jira.atlassian.com revealed that over a 24 hours period we had 48,000 sessions created.  Of these 76% were from web bots out there crawling the site.

This means that nearly 100MB of memory in the java process was holding HttpSession objects.

So to work around this problem in a general sense we put together the atlassian-bot-killer plugin.

This works on sessions by inverting the idea.  A request may have gotten a session but does it deserve to keep it?

What this plugin does is watch every request via a servlet Filter and checks if it has seen the session before.  If not it must be the first request for that session.

It then stores the original session timeout in the session itself and sets the session inactivity timeout to be 1 minute.  If the session makes a second request then it gets bumped back to the original timeout of say 5 hours.  It gets upgraded if you will since we know that the user agent is preserving sessions.

A user behind a web browser often makes a second request milliseconds after the first.  JavaScript, CSS files all count as requests.  So a human user does not notice this at all.

A web bot however does not preserve JSESSIONID cookies and hence is always presenting as a first request.  These will then get a 1 minute time out and hence die quickly.  The memory load on the server is greatly reduced.

REST requests from tools such as curl typically do no preserve sessions either and hence they can fall into the same class of request, even if they are done in terms of a user say via BASIC AUTH.

The atlassian-bot-killer follows the same strategy on requests with a known user however to be conservative it sets the inactivity time out to be 10 minutes instead of 1.

The plugin works on JIRA 4.0 and above so if you have an instance that is publicly available and want t save some session memory load then you can use it.  The atlassian-botkiller plugin is available now on plugins.atlassian.com.

The plugin uses no JIRA specific functionality so in theory it could work on Confluence and Bamboo say.  We haven’t tested that yet so for now its a JIRA only plugin.  We are looking to ship this by default in the next version of JIRA plus we will be reviewing our creation of sessions in general.

Here is the code that saved us 90MB of memory pretty easily.

private void fiddleWithSession(final HttpServletRequest httpServletRequest, final HttpSession httpSession) throws IllegalStateException
{
Integer initialMaxInactiveTimeout = (Integer) httpSession.getAttribute(BotKiller.class.getName());
if (initialMaxInactiveTimeout == null)
{
initialMaxInactiveTimeout = httpSession.getMaxInactiveInterval();
if (initialMaxInactiveTimeout {
return;
}

int lowInactiveTimeout = LOW_INACTIVE_TIMEOUT; // 1 minute
if (thereIsAUserInPlay(httpServletRequest))
{
lowInactiveTimeout = USER_LOW_INACTIVE_TIMEOUT; // 10 minutes
}

httpSession.setMaxInactiveInterval(lowInactiveTimeout);
httpSession.setAttribute(BotKiller.class.getName(), initialMaxInactiveTimeout);

}
else
{
if (httpSession.getMaxInactiveInterval() != initialMaxInactiveTimeout)
{
httpSession.setMaxInactiveInterval(initialMaxInactiveTimeout);

}
}
}

As to whether this will help your JIRA instance, the answer is (as always) it depends.   If your instance is open to the wider internet and hence web bots can be crawling over it then you are likely to be burning session memory and hence this plugin will help you.  The same applies if you have internal REST programs hitting your instance very frequently.

You can tell how many sessions are being created by looking at your atlassian-jira-security.log and grepping how many “session created” statements you have.  The higher the number the more this plugin may help you.

Now I hear you say “you should not be creating sessions for anonymous users” which is the most correct answer but there are mitigating circumstances.

  •  Some libraries create them and we would have to fork them all to get around it.
  • .jsp invocation creates them unless you put in a special directive.
  • Some actual JIRA code wants to put things into the session so that when you subsequently log in you are ready to go.

So even if we want to change the code paths to “not create sessions” for anonymous users we would still have a bunch of engineering trouble and that means time.

The atlassian-bot-killer plugin allows existing instances to get some memory relief and will be part of the solution in future versions of JIRA.