I am using Memcached Session Manager to handle Tomcat sessions in non-sticky mode. My deployment in Azure consists of a Worker Role with two instances which connect to an Azure VM running my Memcached server.

Everything works pretty well, my session is persisted and retrieved by any of the two instances transparently. The problem arises when the session is idle for about 4 minutes; everything points out that the Azure Loadbalancer is closing the spymemcached connection to the VM after some period of inactivity.

My MSM configuration is this:

<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"

The stacktrace printed by the spymemcached client is this:

INFO net.spy.memcached.MemcachedConnection:  Reconnecting due to 
exception on {QA sa=/, #Rops=1, #Wops=0, #iq=0, 
topWop=null, toWrite=0, interested=1} 
java.io.IOException: An existing connection was forcibly closed by the 
remote host 
    at sun.nio.ch.SocketDispatcher.read0(Native Method) 
    at sun.nio.ch.SocketDispatcher.read(Unknown Source) 
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(Unknown Source) 
    at sun.nio.ch.IOUtil.read(Unknown Source) 
    at sun.nio.ch.SocketChannelImpl.read(Unknown Source) 
    at net.spy.memcached.MemcachedConnection.handleReads 
    at net.spy.memcached.MemcachedConnection.handleIO 
    at net.spy.memcached.MemcachedConnection.handleIO 
    at net.spy.memcached.MemcachedClient.run(MemcachedClient.java:1298) 

Given this idle time limitation in Azure, is there any other way to make MSM work in the azure cloud?


There's nothing available to solve this out of the box. But you could subclass MemcachedBackupSessionManager and use the backgroundProcess method (that's invoked by tomcat every second or every 10 secs, not sure about this) to ping your configured memcacheds. A very simple implementation looks like this:

package de.javakaffee.web.msm;

public class MyMsm extends MemcachedBackupSessionManager {

    public void backgroundProcess() {
        final MemcachedNodesManager nodesManager = _msm.getMemcachedNodesManager();
        // got through all configured node ids and ping each memcached
        // with a dummy key.
        // _msm.newSessionId("ping") generates e.g. ping-n1 for a nodeId n1
        // so this will be routed the related memcached node
        for (String nodeId : nodesManager.getPrimaryNodeIds()) {
            // use async here so that no error handling is needed

Then you jar this class, place the jar in $CATALINA_HOME/lib besides msm jars and change the Manager classname to className="de.javakaffee.web.msm.MyMsm".

If you like you can also fork msm and place a pull request with an addition that makes this configurable :-)

  • Great! I'll be glad to contribute :) in the meantime I'll be using this solution. What I don't understand is, how _msm.getMemcached().asyncGet(_msm.newSessionId("ping")); should ping a given node with id nodeId? Wouldn't _msm.getMemcached().asyncGet("ping-" + nodeId); work? – Edgar Pérez Oct 8 '12 at 14:52
  • @EdgarPérez Yes, "ping-" + nodeId is the same as _msm.newSessionId("ping"), with the difference that obviously you have to know how sessionIds are constructed. _msm.newSessionId("ping") hides this and would work even if the format would be changed sometimes. – Martin Grotzke Oct 9 '12 at 9:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.