2015-11-03 3 views
0

Я пытаюсь настроить кластер Tomcat на AWS и так AWS не поддерживает IP многоадресной передачи, один из опции tomcat clustering using DBTomcat Hazelcast Session магазин Session Attributes Исчезновение

Это хорошо понимал, однако, из-за потери производительности связанные с вызовами БД, в настоящее время я рассматриваю Hazelcast как хранилище сеансов. Нынешний подход к фильму Hazelcast не подходит для меня, поскольку в веб-приложении есть другие фильтры, и они несколько мешают, и лучший и более чистый подход состоял бы в том, чтобы настроить PersistenceManager с помощью реализации пользовательского хранилища и настроить его на tomcat/конф 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 и след от кота ниже:

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

выше след, если от " save ', как переопределенная реализацией магазина, код приведен ниже:

@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 секунд.

Однако атрибут сеанса потерян (новый), старые все еще существуют. Но независимо от того, какой метод «нагрузки» не называется (по крайней мере, я не вижу след).

Некоторая помощь в этом будет по достоинству оценена.

+0

странно. из вы бы сделали это, но все же, чтобы подтвердить это - вы положили некоторые заявления печати/отладки, чтобы увидеть, если load() когда-либо попал? – Dinesh

+0

Да, есть инструкции печати, в 'load', как в save, см. Приведенный выше код, он также печатает атрибуты, связанные с сеансом, спасибо – Ironluca

+1

Я видел код. Я специально указывал на отладочные заявления сразу после load() (чего я не вижу здесь). Поскольку readObject является блокирующим вызовом. – Dinesh

ответ

0

Надеется, что это поможет кому-то, проблема на самом деле в следующих разделах кода:

общественность недействительный сохранить (сессионный Session) бросает метод 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); 

общественной сессия нагрузки (String SESSIONID) подбрасывает ClassNotFoundException , 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(); 

Если вы заметили, сессия суммарно сериализованная и сохраняется в Hazelcast, что не Prob сам по себе.

Теперь, если мы посмотрим на код Tomcat для StandardSession, мы видим, что он содержит ряд переходных свойств, которые не будут сериализованы. Поэтому во время десериализации эти свойства должны иметь значения, которые выполняются в методе «load», однако это делается неправильно, сначала он десериализует сеанс из метода ObjectOputStream «readObjectData» для инициализации свойств переходного процесса. В стандартном представлении «readObjectData» вызывает «doReadObject» защищенный метод для повторной инициализации переходных свойств, что, в свою очередь, предполагает, что предоставленный поток объектов представляет собой серию объектов.В нашем случае, однако, это весь сериализованный объект, а не ряд объектов, которые он ожидает.

Фактически после включения точного контроля уровня на Tomcat это исключение видно только в противном случае.

Обходной путь прост, стандартSession имеет метод writeObjectData, который внутренне вызывает защищенный метод doWriteObject, который записывает состояние сеанса в ряд объектов в выходной поток, считывая эти сериализованные байты, решает проблему ,

 Смежные вопросы

  • Нет связанных вопросов^_^