我試圖安裝一個Tomcat集羣上的AWS和自AWS不支持IP多播,選項之一是tomcat clustering using DBTomcat的Hazelcast會話存儲會話屬性消失
,非常然而理解,由於性能損失與數據庫調用相關,我目前正在考慮將Hazelcast作爲會話存儲。目前的Hazelcast過濾器方法並不適合我,因爲Web應用程序上有其他過濾器,它們有點干擾,更好和更乾淨的方法是使用自定義商店實現配置PersistenceManager,並在tomcat/CONF context.xml中,配置部提供如下:
<Manager className="org.apache.catalina.session.PersistentManager"
distributable="true"
maxActiveSessions="-1"
maxIdleBackup="2"
maxIdleSwap="5"
processingTime="1000"
saveOnRestart="true"
maxInactiveInterval="1200">
<Store className="com.hm.vigil.platform.session.HC_SessionStore"/>
</Manager>
的會話正在被保存在Hazelcast實例並從Tomcat跟蹤低於:
---------------------------------------------------------------------------------------
HC_SessionStore == Saving Session ID == C19A496F2BB9E6A4A55E70865261FC9F SESSION == StandardSession[
C19A496F2BB9E6A4A55E70865261FC9F]
SESSION ATTRIBUTE :: USER_IDENTIFIER :: 50
SESSION ATTRIBUTE :: APPLICATION_IDENTIFIER :: APPLICATION_1
SESSION ATTRIBUTE :: USER_EMAIL :: [email protected]
SESSION ATTRIBUTE :: USER_ROLES :: [PLATFORM_ADMIN, CLIENT_ADMIN, PEN_TESTER, USER]
SESSION ATTRIBUTE :: CLIENT_IDENTIFIER :: 1
---------------------------------------------------------------------------------------
03-Nov-2015 15:12:02.562 FINE [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.ca
talina.session.PersistentManagerBase.processExpires End expire sessions PersistentManager processing
Time 75 expired sessions: 0
03-Nov-2015 15:12:02.563 FINE [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.ca
talina.session.PersistentManagerBase.processExpires Start expire sessions PersistentManager at 14465
43722563 sessioncount 0
03-Nov-2015 15:12:02.577 FINE [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.ca
talina.session.PersistentManagerBase.processExpires End expire sessions PersistentManager processing
Time 14 expired sessions: 0
上述跟蹤如果從'保存'方法由商店實施覆蓋,代碼如下:
@Override
public void save(Session session) throws IOException {
//System.out.println("HC_SessionStore == Saving Session ID == "+session.getId()+" SESSION == "+session);
try{
String sessionId=session.getId();
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(session);
oos.close();
byte[] serializedSession=baos.toByteArray();
sessionStore.put(sessionId,serializedSession);
sessionCounter++;
System.out.println("---------------------------------------------------------------------------------------");
System.out.println("HC_SessionStore == Saving Session ID == "+sessionId+" SESSION == "+session);
Enumeration<String> attributeNames=((StandardSession)session).getAttributeNames();
while(attributeNames.hasMoreElements()){
String attributeName=attributeNames.nextElement();
System.out.println("SESSION ATTRIBUTE :: "+attributeName+" :: "+((StandardSession)session).getAttribute(attributeName));
}//while closing
System.out.println("---------------------------------------------------------------------------------------");
}catch(Exception e){throw new IOException(e);}
}//save closing
'sessionStore'是一個Hazelcast分佈式地圖。
商店的相應的「負載」的方法如下:
@Override
public Session load(String sessionId) throws ClassNotFoundException, IOException {
Session session=null;
try{
byte[] serializedSession=(byte[])sessionStore.get(sessionId);
ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(serializedSession));
//Read the saved session from serialized state
//StandardSession session_=new StandardSession(manager);
StandardSession session_=(StandardSession)ois.readObject();
session_.setManager(manager);
ois.close();
//Initialize the transient properties of the session
ois=new ObjectInputStream(new ByteArrayInputStream(serializedSession));
session_.readObjectData(ois);
session=session_;
ois.close();
System.out.println("===========================================================");
System.out.println("HC_SessionStore == Loading Session ID == "+sessionId+" SESSION == "+session);
Enumeration<String> attributeNames=session_.getAttributeNames();
while(attributeNames.hasMoreElements()){
String attributeName=attributeNames.nextElement();
System.out.println("SESSION ATTRIBUTE :: "+attributeName+" :: "+session_.getAttribute(attributeName));
}//while closing
System.out.println("===========================================================");
}catch(Exception e){throw new IOException(e);}
return session;
}//load closing
現在,最有趣的事情之一是,雖然「存儲」方法被調用,在60秒的默認間隔, 'load'方法永遠不會被調用,淨影響是所有保存的會話屬性在一段時間後都會丟失,這是最不尋常的。從技術上講,綁定到會話的任何新會話屬性都將保存在Hazelcast中,一旦調用「save」方法並且管理器被配置爲每5秒換出一次。
但是,會話屬性丟失(新的),舊的仍然存在。但不管它是什麼「負載」方法都沒有被調用(至少我沒有看到跟蹤)。
對此的一些幫助將非常感激。
奇怪。 ofc你會做到這一點,但仍然要確認 - 你有打印報告/調試點,看看load()是否被擊中? – Dinesh
是的,有打印語句,在'load'中保存,請參考上面的代碼,它也打印綁定到會話的屬性,謝謝 – Ironluca
我看到了代碼。我特別指出了load()後的調試語句(我在這裏沒有看到)。由於readObject是一個阻塞呼叫。 – Dinesh