Tomcat Web Application - хранение объектов в виде пользовательских объектов или простых идентификаторов для сохранения пользовательских сессий при перезагрузке сервера? - PullRequest
5 голосов
/ 12 мая 2011

Допустим, у нас есть веб-приложение, поддерживаемое механизмом / контейнером сервлетов, таким как Tomcat. Пользователь входит в систему. Загружается запись базы данных для этого пользователя (например, представленная экземпляром класса User), и мы можем сохранить его как атрибут сеанса с ключом «currentUser», установить его один раз и использовать для обрабатывать последующие запросы. Кроме того, мы помещаем больше объектов в атрибут сеанса. Довольно простые вещи.

Теперь, если нам нужно развернуть новый код и перезагрузить Tomcat ... Сеансы пользователей после перезагрузки остаются нетронутыми (восстанавливается с disk / db) , пока мы не изменим ни один из классов, чьи экземпляры хранятся в сеансе пользователя . Но это большая проблема. Я не хочу, чтобы пользователи теряли свои сессии при выпуске нового кода.

Чтобы обойти эту проблему, я полагаю, что я могу хранить в объекте сеанса только экземпляры классов, которые, как предполагается, никогда не изменятся (например, хранение идентификатора вошедшего в систему пользователя как Integer, а не экземпляра User учебный класс). Тогда я бы никогда не столкнулся с проблемой невозможности десериализации объекта сеанса после перезагрузки. Но это немного усложняет ситуацию, поскольку теперь мне нужно использовать идентификатор для загрузки реального объекта из базы данных и т. Д. (А при кэшировании снижение производительности не является проблемой).

Это то, что обычно делается, чтобы обойти эту проблему?

Ответы [ 3 ]

3 голосов
/ 12 мая 2011

Простое решение

Как вы предложили, загрузите только идентификатор пользователя в вашем сеансе и используйте службу кэширования, такую ​​как ehcache, для извлечения пользовательских объектов. Если пользовательский объект не существует, он будет загружен в первый раз, но затем он будет кэширован, а последующие запросы будут выполняться довольно быстро. Если вас беспокоит изменение класса пользователя, делайте кэш-память только на основе, чтобы она перезагружалась между перезагрузками сервера.

Платформенное решение

Взгляните на Terracotta (http://www.terracotta.org/). Если вы сможете развернуть свои сеансы на их платформе, они позволят вам поддерживать их между перезагрузками сервера, а также обновлять фактический класс пользователя, сохраняя старые поля. Довольно крутые вещи как только у вас все заработало.

Имейте в виду, что интеграция с терракотой не простая и не для новичков. Однако преимуществами являются масштабируемость и высокая доступность, которые требуются для всех веб-приложений.

2 голосов
/ 12 мая 2011

Что касается сериализации, то при условии, что вы не измените формат сериализации, это не будет проблемой.В противном случае вы получите страшную InvalidClassException .Что вам нужно сделать, это:

  1. Установите serialVersionUID для каждого объекта, который вы сериализуете: при условии, что вы не измените поля в классе между перезагрузками, этого должно быть достаточно.
  2. Переопределите методы writeObject / readObject для точного управления форматом сериализации: если вы сделаете это, вы можете даже обойти радикальные изменения в классе.
  3. Использовать JSON / XML или любой другойформат хранения, который чисто обрабатывает перевод.Возможно, ваша лучшая ставка.
1 голос
/ 12 мая 2011

Интересная ситуация и хороший вопрос.

Как правило, из того, что я видел в корпоративных средах, сеансы обычно завершаются после развертывания новой версии веб-приложения - так как в любом случае это новое развертывание, приложениеСервер обычно не знает разницы между новым приложением и новой версией.Я не думаю, что было бы хорошей идеей, если бы серверы сохраняли сеансы, поскольку это может быть просто совершенно другое приложение, для которого у пользователя могут отсутствовать какие-либо разрешения на доступ и т. Д., Так что это может быть проблемой безопасности.

Однако давайте предположим, что сеансы будут сохраняться и могут быть восстановлены даже для новых развертываний.То, как вы описываете, звучит почти правильно, вы также можете сделать это немного сложнее, например, проверить, есть ли в сеансе старые объекты, которые необходимо преобразовать (или снова загрузить из базы данных) в зависимости от их версии.В Java вы бы очень старались, чтобы ваши классы были двоично-совместимыми, поэтому новая версия приложения все еще может десериализовать его.Вот для чего предназначены writeObject / readObject.

Другая идея - сохранить «сеанс» в вашем собственном формате данных в базе данных и использовать сеанс только для легких данных, таких как аутентификация пользователя и собственный идентификатор сеанса приложения,Я никогда не видел такого в Java-приложении, но он позволяет делать то, что вы хотите, и выполнять шаги миграции во время развертывания для переноса данных в новый формат.Вместе с файлами cookie для автоматического входа и запоминания ваши пользователи не увидят никакой разницы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...