JETTY-776

Remove LightLoad test as this is not applicable for the JDBC solution. It only works with terracotta because terracotta takes out a cluster-wide lock when the session is entered on any node. This means you can bounce the session around nodes. This does not work with the JDBC session implementation as it is not feasible to do a cluster-wide lock on particular row on the sessions table.

Add a method on JDBCSessionManager that would allow a subclass to send a message to all other nodes whenever the session is being written to the database which would cause the other nodes to invalidate that session in their local caches and re-read from the database.


git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@1218 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Jan Bartel 2010-01-28 00:54:40 +00:00
parent 4d65767692
commit c378bc797b
3 changed files with 38 additions and 46 deletions

View File

@ -74,7 +74,7 @@ public class JDBCSessionManager extends AbstractSessionManager
private ConcurrentHashMap _sessions;
protected long _saveIntervalSec = 60; //only persist changes to session access times every 60 secs
/**
* SessionData
*
@ -334,7 +334,7 @@ public class JDBCSessionManager extends AbstractSessionManager
try
{
if (_dirty)
{
{
//The session attributes have changed, write to the db, ensuring
//http passivation/activation listeners called
willPassivate();
@ -342,8 +342,9 @@ public class JDBCSessionManager extends AbstractSessionManager
didActivate();
}
else if ((_data._accessed - _data._lastSaved) >= (getSaveInterval() * 1000))
{
updateSessionAccessTime(_data);
}
}
catch (Exception e)
{
@ -429,6 +430,24 @@ public class JDBCSessionManager extends AbstractSessionManager
}
/**
* A method that can be implemented in subclasses to support
* distributed caching of sessions. This method will be
* called whenever the session is written to the database
* because the session data has changed.
*
* This could be used eg with a JMS backplane to notify nodes
* that the session has changed and to delete the session from
* the node's cache, and re-read it from the database.
* @param idInCluster
*/
public void cacheInvalidate (Session session)
{
}
/**
* A session has been requested by it's id on this node.
*
@ -454,13 +473,14 @@ public class JDBCSessionManager extends AbstractSessionManager
{
try
{
//check if we need to reload the session - don't do it on every call
//check if we need to reload the session -
//as an optimization, don't reload on every access
//to reduce the load on the database. This introduces a window of
//possibility that the node may decide that the session is local to it,
//when the session has actually been live on another node, and then
//re-migrated to this node. This should be an extremely rare occurrence,
//as load-balancers are generally well-behaved and consistently send
//sessions to the same node, changing only iff that node fails.
//sessions to the same node, changing only iff that node fails.
SessionData data = null;
long now = System.currentTimeMillis();
if (Log.isDebugEnabled()) Log.debug("now="+now+
@ -469,16 +489,19 @@ public class JDBCSessionManager extends AbstractSessionManager
" difference="+(now - (session==null?0:session._data._lastSaved)));
if (session==null || ((now - session._data._lastSaved) >= (_saveIntervalSec * 1000)))
{
{
data = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context));
}
else
{
data = session._data;
}
if (data != null)
{
if (!data.getLastNode().equals(getIdManager().getWorkerName()) || session==null)
{
//if the session in the database has not already expired
if (data._expiryTime > System.currentTimeMillis())
{

View File

@ -26,6 +26,8 @@ public class JdbcTestServer extends AbstractTestServer
public static final String CONNECTION_URL = "jdbc:derby:sessions;create=true";
public static final int SAVE_INTERVAL = 1;
protected boolean _optimize = true;
static
{
System.setProperty("derby.system.home", System.getProperty("java.io.tmpdir"));
@ -41,7 +43,12 @@ public class JdbcTestServer extends AbstractTestServer
super(port, maxInactivePeriod, scavengePeriod);
}
public JdbcTestServer (int port, boolean optimize)
{
super(port);
_optimize=optimize;
}
/**
* @see org.eclipse.jetty.server.session.AbstractTestServer#newSessionHandler(org.eclipse.jetty.server.SessionManager)
*/
@ -73,6 +80,7 @@ public class JdbcTestServer extends AbstractTestServer
JDBCSessionManager manager = new JDBCSessionManager();
manager.setIdManager((JDBCSessionIdManager)_sessionIdManager);
manager.setSaveInterval(SAVE_INTERVAL); //ensure we save any changes to the session at least once per second
manager.setOptimizeDbAccess(_optimize); //or go to the database every time
return manager;
}

View File

@ -1,39 +0,0 @@
//========================================================================
//Copyright 2010 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server.session;
import org.testng.annotations.Test;
/**
* LightLoadTest
*
*
*/
public class LightLoadTest extends AbstractLightLoadTest
{
public AbstractTestServer createServer(int port)
{
return new JdbcTestServer(port);
}
@Test(groups={"jdbc-all"})
public void testLightLoad() throws Exception
{
super.testLightLoad();
}
}