Archives for: June 2009, 18

06/18/09

Permalink 02:41:44 pm, by nogunner Email , 740 words   English (US)
Categories: Misc

Jdbc Jutsu Saves Heap Memory Against Wicket's Stateful Ajax

Hey, I hope Quentin Tarantino won't steal my title and make a movie out of it! Anyway, the Wicket's implementation of Ajax is so good that I just stopped using anything else to make my web client communicate with my server. There's this one thing however, that prevents the fine scaling of Wicket sites, that's namely memory consumption. Wicket by itself does not consume that much memory though, but if you want to use the sweet Ajax components, you're stuck with stateful pages. And using stateful pages + lots of visitors usually implies memory issues: it's not just your own data contained in the WebSession object that is stored in memory, but also the current page hosting the ajax components, and the n last pages visited. If your pages are big, the session are big, that's the point.

Add to that a specific need to make the session last longer than usual, to allow users to stop using the site, then going back after a long period of time, and still have their session available, and you'd rapidly be waiting your users with fear.

So, to conciliate long sessions, limited-memory servers, and stateful wicket, the best possible solution, besides asking your users not to tell their friends, is to apply a Jdbc Jutsu to the session management of your servlet container. At least, that's how I solve my issue.

Tomcat provides a JDBCStore for its PersistentManager class (which is responsible for managing the sessions): this java jutsu just saved my server's memory from going out of control. Unlike the default org.apache.catalina.session.StandardManager that stores everything in your precious heap memory, the PersistentManager provides a lot of flexibility regarding the session storage. For instance, a typical configuration would keep the sessions in-memory, but passivate them into a database after a few minutes of inactivity (instead of consuming all this good memory for idle or disconnected users until their session expires).

The Tomcat documentation lacks a few examples, so here's mine: I wanted unlimited sessions, and passivate idle sessions in the JDBC database after 120 seconds of inactivity (lines to customize are yellow).

  <Host ......
	  <Context path="/MYPATH" docBase="MY-APPLICATION.WAR">
	    <Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true" 
		     maxIdleSwap="120"
		     minIdleSwap="-1" 
		     maxActiveSessions="-1"
		     maxIdleBackup="-1">
	      <Store className="org.apache.catalina.session.JDBCStore"

		     driverName="com.mysql.jdbc.Driver"
		     connectionURL="jdbc:mysql://localhost/MYAPP"
		     connectionName="DATABASE-USERNAME"
		     connectionPassword="DATABASE-PASSWORD"

		     sessionTable="tomcat_sessions"
		     sessionIdCol="session_id"
		     sessionValidCol="valid_session"
		     sessionMaxInactiveCol="max_inactive"
		     sessionLastAccessedCol="last_access"
		     sessionAppCol="app_name"
		     sessionDataCol="session_data"

		     checkInterval="60"
		    />
	      </Manager> 
	  </Context>
  </Host>
Note: Remember to put your jdbc driver jar in the lib/ folder of Tomcat, or the connection won't work.

Then in the database and schema specified in the configuration above, just add the following table:
(from the Tomcat Manual at http://tomcat.apache.org/tomcat-6.0-doc/config/manager.html):

create table tomcat_sessions (
  session_id     varchar(100) not null primary key,
  valid_session  char(1) not null,
  max_inactive   int not null,
  last_access    bigint not null,
  app_name       varchar(255),
  session_data   mediumblob,
  KEY kapp_name(app_name)
);

Well, that's it, no more wicket-related memory issues.

Update after Thyzz comment (see below)

Wicket can actually use either its original HttpSessionStore (that stores everything in the servlet http session), or its new SecondLevelCacheSessionStore that stores the PageMap on disk. Here is below some metrics I made that compare the memory usage with and without the tomcat's JDBCStore:


(click to enlarge)

To get those metrics, I used a web application that makes a moderate memory usage, and changed it so that the SessionStore can be either the HttpSessionStore or the SecondLevelCacheSessionStore. Additionnally, I added a new byte[1024*500] allocation into the session object, so that the memory consumption be artificially higher (for the purpose of testing in this specific configuration, applications with a really low memory footprint of their session behave totally differently, and are unlikely to have any memory-related issue). Then I ran a script on another computer that would make a loop over an http request for the frontpage (and all the resources of that page).

As a result, both HttpSessionStore and SecondLevelCacheSessionStore end up with an OutOfMemoryException. The memory usage is slightly better when using the SecondLevelCacheSessionStore, but I did not test the http latency; a real benchmark would require to compare both memory and speed, but at least the figures shows that the memory issue is prevented.

nogunner's blog

Pointless technical stuffs are the bomb diggity of life.

June 2009
Sun Mon Tue Wed Thu Fri Sat
 << < Current> >>
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        

Search

XML Feeds

Web Monitoring

Be sure to check my LinkLogics web monitoring application if you happen to need external monitoring.
powered by b2evolution free blog software