467055 Mongodb session scavenging can result in very slow query

This commit is contained in:
Jan Bartel 2015-05-15 17:03:38 +10:00
parent 3c7d550295
commit f6c1cc46d8
2 changed files with 64 additions and 6 deletions

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.nosql.mongodb;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -117,6 +118,8 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
* The maximum number of items to return from a purge query. * The maximum number of items to return from a purge query.
*/ */
private int _purgeLimit = 0; private int _purgeLimit = 0;
private int _scavengeBlockSize;
/** /**
@ -210,12 +213,46 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
* - the expiry time has passed * - the expiry time has passed
* *
* we limit the query to return just the __ID so we are not sucking back full sessions * we limit the query to return just the __ID so we are not sucking back full sessions
*
* break scavenge query into blocks for faster mongo queries
*/ */
BasicDBObject query = new BasicDBObject(); Set<String> block = new HashSet<String>();
query.put(MongoSessionManager.__ID,new BasicDBObject("$in", _sessionsIds ));
query.put(MongoSessionManager.__EXPIRY, new BasicDBObject("$gt", 0)); Iterator<String> itor = _sessionsIds.iterator();
query.put(MongoSessionManager.__EXPIRY, new BasicDBObject("$lt", now)); while (itor.hasNext())
{
block.add(itor.next());
if ((_scavengeBlockSize > 0) && (block.size() == _scavengeBlockSize))
{
//got a block
scavengeBlock (now, block);
//reset for next run
block.clear();
}
}
//non evenly divisble block size, or doing it all at once
if (!block.isEmpty())
scavengeBlock(now, block);
}
/* ------------------------------------------------------------ */
/**
* Check a block of session ids for expiry and thus scavenge.
*
* @param atTime
* @param ids
*/
protected void scavengeBlock (long atTime, Set<String> ids)
{
if (ids == null)
return;
BasicDBObject query = new BasicDBObject();
query.put(MongoSessionManager.__ID,new BasicDBObject("$in", ids ));
query.put(MongoSessionManager.__EXPIRY, new BasicDBObject("$gt", 0));
query.put(MongoSessionManager.__EXPIRY, new BasicDBObject("$lt", atTime));
DBCursor checkSessions = _sessions.find(query, new BasicDBObject(MongoSessionManager.__ID, 1)); DBCursor checkSessions = _sessions.find(query, new BasicDBObject(MongoSessionManager.__ID, 1));
@ -223,7 +260,7 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
{ {
__log.debug("SessionIdManager:scavenge: expiring session {}", (String)session.get(MongoSessionManager.__ID)); __log.debug("SessionIdManager:scavenge: expiring session {}", (String)session.get(MongoSessionManager.__ID));
expireAll((String)session.get(MongoSessionManager.__ID)); expireAll((String)session.get(MongoSessionManager.__ID));
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -373,7 +410,26 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
_scavengePeriod = TimeUnit.SECONDS.toMillis(scavengePeriod); _scavengePeriod = TimeUnit.SECONDS.toMillis(scavengePeriod);
} }
/* ------------------------------------------------------------ */
/** When scavenging, the max number of session ids in the query.
*
* @param size
*/
public void setScavengeBlockSize (int size)
{
_scavengeBlockSize = size;
}
/* ------------------------------------------------------------ */
/**
* @return
*/
public int getScavengeBlockSize ()
{
return _scavengeBlockSize;
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* The maximum number of items to return from a purge query. If <= 0 there is no limit. Defaults to 0 * The maximum number of items to return from a purge query. If <= 0 there is no limit. Defaults to 0

View File

@ -27,7 +27,9 @@ public class LocalSessionScavengingTest extends AbstractLocalSessionScavengingTe
@Override @Override
public AbstractTestServer createServer(int port, int max, int scavenge) public AbstractTestServer createServer(int port, int max, int scavenge)
{ {
return new MongoTestServer(port,max,scavenge); MongoTestServer mserver=new MongoTestServer(port,max,scavenge);
((MongoSessionIdManager)mserver.getServer().getSessionIdManager()).setScavengeBlockSize(0);
return mserver;
} }
@Override @Override