我在用Memcached 会话管理器处理 Tomcat 会话非粘性模式。我在 Azure 中的部署由一个具有两个实例的工作角色组成,它们连接到运行我的 Memcached 服务器的 Azure VM。
一切运行良好,我的会话被两个实例中的任何一个透明地持久化和检索。当会话空闲大约4 分钟;一切都表明,Azure Loadbalancer 在一段时间不活动后关闭了与 VM 的 spymemcached 连接。
我的 MSM 配置如下:
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:my-azure-vm.cloudapp.net:11211"
sticky="false"
sessionBackupAsync="false"
sessionBackupTimeout="10000"
lockingMode="uriPattern:/path1|/path2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js|ttf|eot|svg|woff)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
customConverter="de.javakaffee.web.msm.serializer.kryo.HibernateCollectionsSerializerFactory"/>
spymemcached 客户端打印的堆栈跟踪如下:
INFO net.spy.memcached.MemcachedConnection: Reconnecting due to
exception on {QA sa=/10.194.132.206:13000, #Rops=1, #Wops=0, #iq=0,
topRop=net.spy.memcached.protocol.binary.StoreOperationImpl@1d95da8,
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
(MemcachedConnection.java:303)
at net.spy.memcached.MemcachedConnection.handleIO
(MemcachedConnection.java:264)
at net.spy.memcached.MemcachedConnection.handleIO
(MemcachedConnection.java:184)
at net.spy.memcached.MemcachedClient.run(MemcachedClient.java:1298)
鉴于 Azure 中的这个空闲时间限制,还有其他方法可以让 MSM 在 Azure 云中工作吗?
答案1
目前没有现成的方法可以解决这个问题。但你可以将 MemcachedBackupSessionManager 子类化,并使用该backgroundProcess
方法(由 tomcat 每秒或每 10 秒调用一次,不确定)来 ping 你配置的 memcached。一个非常简单的实现如下所示:
package de.javakaffee.web.msm;
public class MyMsm extends MemcachedBackupSessionManager {
@Override
public void backgroundProcess() {
super.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
_msm.getMemcached().asyncGet(_msm.newSessionId("ping"));
}
}
}
然后将这个类打包成 jar,将 jar 放在 $CATALINA_HOME/lib 中 msm jars 旁边,然后将 Manager 类名更改为className="de.javakaffee.web.msm.MyMsm"
。
如果你愿意,你也可以 fork msm 并发出拉取请求,添加一些内容以使其可配置 :-)