2015-11-03 1 views
0

Je suis en train d'installer un cluster Tomcat sur AWS et depuis AWS ne prend pas en charge la multidiffusion IP, l'une des options est tomcat clustering using DBTomcat Session Hazelcast session Magasin Attributs Vanishing

qui est bien compris, cependant, en raison des pénalités de performance lié aux appels DB, je considère actuellement Hazelcast comme le magasin de session. L'approche actuelle du filtre Hazelcast ne fonctionne pas pour moi car il y a d'autres filtres sur l'application web et ils interfèrent quelque peu et une approche meilleure et plus simple serait de configurer PersistenceManager avec une implémentation personnalisée et de le configurer sur le tomcat/conf context.xml, la section de configuration est fourni ci-dessous:

<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> 

les sessions sont enregistrées dans l'instance Hazelcast et la trace de tomcat est ci-dessous:

--------------------------------------------------------------------------------------- 
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 

la trace ci-dessus, si de la ' save 'méthode comme substituée par l'implémentation du magasin, le code est fourni ci-dessous:Où 'sessionStore' est une carte distribuée Hazelcast.

La méthode « charge » correspondante du magasin se présente comme suit:

@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 

Maintenant, l'une des choses les plus intriguant est que si la méthode du « magasin » est appelé à l'intervalle par défaut de 60 secondes, la méthode 'load' n'est jamais appelée avec l'impact net que les attributs de session sauvegardés sont perdus après un certain temps, ce qui est inhabituel. Techniquement, tous les nouveaux attributs de session liés à la session seront sauvegardés dans la Hazelcast une fois que la méthode 'save' sera appelée et que le gestionnaire sera configuré pour échanger toutes les 5 secondes.

Cependant, l'attribut de session est perdu (le nouveau), les anciens sont toujours là. Mais quelle que soit la méthode 'load' n'est pas appelée (au moins je ne vois pas la trace).

Une aide à ce sujet sera vraiment appréciée.

+0

étrange. ofc vous l'auriez fait mais encore à confirmer - avez-vous mis quelques instructions d'impression/points de débogage pour voir si load() est jamais touché? – Dinesh

+0

Oui, il y a des déclarations d'impression, en « charge » comme sauvegarde, s'il vous plaît se référer le code ci-dessus, il imprime aussi les attributs liés à la session, grâce – Ironluca

+1

j'ai vu le code. Je pointais spécifiquement sur les instructions de débogage juste après le chargement() (que je ne vois pas ici). Depuis readObject est un appel bloquant. – Dinesh

Répondre

0

Hope this helps quelqu'un, le problème est en fait dans les sections de code suivant:

public void save (session de session) throws méthode IOException:

 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); 

charge de session publique (String sessionId) lancers francs ClassNotFoundException , méthode IOException:

 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(); 

Si vous remarquez, la session est sommairement sérialisé et enregistré au Hazelcast, qui n'est pas un prob lem par lui-même.

Maintenant, si nous regardons le code Tomcat pour StandardSession, nous voyons qu'il contient un certain nombre de propriétés transitoires qui ne seront pas sérialisées. Ainsi, lors de la désérialisation, ces propriétés doivent recevoir des valeurs, ce qui est fait dans la méthode 'load'. Cependant, cela se passe mal, d'abord désérialiser la session de la méthode ObjectInputStream 'readObjectData' pour initialiser les propriétés transitoires. Dans la session standard, 'readObjectData' appelle 'doReadObject' une méthode protégée pour réinitialiser les propriétés transitoires, qui à son tour s'attend à ce que le flux d'entrée d'objet fourni soit une série d'objets.Dans notre cas, cependant, c'est l'objet sérialisé entier et non la série d'objets qu'il attend.

En fait, après l'activation de l'enregistrement de niveau bien sur Tomcat que cette exception est vu, pas autrement. La solution de contournement est simple, StandardSession a une méthode méthode 'writeObjectData', qui appelle en interne une méthode protégée 'doWriteObject', qui écrit l'état de session dans une série d'objets dans le flux de sortie, lire ces octets sérialisés résout le problème .