Управление сеансами WebApp с использованием Ehcache - PullRequest
6 голосов
/ 09 октября 2011

В моем проекте я использую ehcache для хранения зарегистрированных в системе сведений о пользователе и некоторой другой информации (какое приложение будет использовать это во время выполнения вместо выборки из базы данных). Вот моя конфигурация ehcache:

<cache 
    name="normalCache"
    maxElementsInMemory="50000" 
    eternal="false"
    timeToIdleSeconds="1800" 
    timeToLiveSeconds="0"
    overflowToDisk="false"
    memoryStoreEvictionPolicy="LRU"
/>

Но проблема в том, что в большинстве случаев происходит тайм-аут сеанса (даже если пользователь не активен больше> 30). Иногда это происходит в течение 10 минут, ...

Все действия будут пытаться получить пользовательский объект для каждого запроса из ehcache.

Я не уверен, как ehcache определит время истечения.

Ответы [ 3 ]

5 голосов
/ 15 февраля 2014

Ehcache извлекает объекты из кэша при выполнении одного из следующих условий:

  1. Объект не был доступен из ehcache (для чтения или обновления) в течение более timeToIdle секунд. Это правило не применяется, если timeToIdle не установлено. Другими словами, объект может оставаться в кэше в течение бесконечного времени, даже если к нему никогда не осуществляется доступ (чтение или обновление) из кэша, когда timeToIdle не задано.

  2. Объект находился в кэше более timeToLive секунд. Это правило не применяется, если timeToLive не установлено. Другими словами, объект может оставаться в кэше бесконечное время.

  3. Количество элементов в кэше достигло предела maxElementsInMemory. В этом случае memoryStoreEvictionPolicy вступает в действие и удаляет элементы, соответствующие политике вытеснения, до тех пор, пока количество элементов в кэше не станет меньше предела maxElementsInMemory, даже если эти элементы квалифицированы как находящиеся в кэше согласно условию № 1 и № 2.

Надеюсь, что это проясняет!

1 голос
/ 12 февраля 2014

ehcache не гарантирует сохранение всех ваших элементов в течение 30 минут.

В вашей конфигурации у вас maxElementsInMemory 50000. Возможно, вы в какой-то момент достигли 50000 и, следовательно,запись «Наименее недавно использованные» будет удалена, поскольку вы установили для overflowToDisk значение false.

0 голосов
/ 17 февраля 2014

Преамбула

Если вы планируете использовать ehCache в качестве первой проверки реализации управления сеансом, если вы не можете случайно использовать уже предоставленную и, вероятно, более подходящую реализацию сеанса. Если вы используете веб-контейнер или полноценный jee-сервер, вам действительно стоит попробовать это сначала


Почему

Хорошо. Вы уверены, что не сделаете это правильным легким способом. Вот несколько советов, почему вы можете использовать ehCache для сессий

  1. Ваш сервис не является частью jee-сервера / веб-контейнера.
  2. Ваш сервис не имеет состояния, но время от времени вам нужны состояния (код структуры).
  3. Вы не можете различать вызовы из-за того, что между вами и различимым клиентом находится прокси-сервер, например, вы являетесь своего рода промежуточным ПО для службы / службы, которое не предоставляет различимые данные по умолчанию, но использует такие параметры, как userId или sessionId, условно, но не конститутивно .
  4. Вы просто не RTFM и хотите сделать это по-своему.

Для 1, пожалуйста, проверьте, если веб-контейнер, как причал, вариант. Вы, конечно, используете веб-доступ ко всему сеансу, что бы вам не показалось.

Для 2, пожалуйста, проверьте, если Apache Shiro не будет делать то, что вы хотите. Если нет, ehCache может быть вашим другом.

На 3 ... добро пожаловать в клуб.

Для 4 ... ну, я думаю, что если вы не читали руководство, вы тоже не прочтете.


Как

Если вы хотите реализовать управление сеансами с помощью ehCache, убедитесь, что ваши данные сериализуемы. Это уменьшит проблемы и позволит вам использовать конфиденциальные функции ehCache. а именно сохранение на диск, кеширование узлов, восстановление после этого и т. д.

Do not использовать кеш для каждой сессии, но one cache для всех сессий. sessionId - это ключ в вашем кеше, а значения равны Map. Не забывайте о параллелизме (вспомните ajax-вызовы). Лучше всего использовать ConcurrentHashMap из java.util.concurrent. Но, может быть, вы доктор Хайнц М. Кабуц и найдете еще более клёвый способ сделать это.

Мне показалось очень полезным использовать размер, а не количество элементов для хранения. Вы можете не знать, какие данные / объекты хранятся позже. Не забудьте установить постоянную стратегию. Я использовал хранение во временную папку здесь.

<?xml version="1.0" encoding="UTF-8"?>
<ehcache
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="ehcache.xsd"
    updateCheck="true"
    monitoring="autodetect"
    dynamicConfig="true">

    <diskStore path="java.io.tmpdir"/>

    <cache name="vocCache"
        eternal="false"
        maxElementsInMemory="100MB"
        maxElementsOnDisk="1GB"
    timeToIdleSeconds="3600"
    timeToLiveSeconds="0"
    memoryStoreEvictionPolicy="LRU"
    diskExpiryThreadIntervalSeconds="60">
    <persistence strategy="localTempSwap" />
</cache>

Поскольку мы хотим реализовать менеджер сеансов, мы не беспокоимся о timeToLiveSeconds. Тайм-аут сеансов после определенного времени простоя. Таким образом, мы не ограничиваем элемент максимальным значением ttl, а используем timeToIdleSeconds, чтобы позволить элементу истечь. Не беспокойтесь о timeToIdleSeconds и timeToLiveSeconds, потому что вы можете установить определенные значения для элементов, которые будут добавлены позже.

Выселение

Одна заметка о времени истечения. Элемент в памяти никогда не будет выселен из-за настроенного времени. Память будет накапливаться до тех пор, пока не будет достигнуто указанное ограничение памяти. Поэтому, если вы определите 100 элементов, если будет добавлен элемент 101, memoryStoreEvictionPolicy сделает ставку, и один элемент - в этой конфигурации - будет сброшен на диск (ehCache 2.2). Для дискового хранилища будет проверка потока на время истечения (diskExpiryThreadIntervalSeconds). См. документацию . Поэтому вы должны проверить извлеченный элемент из кэша, используя isExpired(), чтобы убедиться, что он не истек.


Итак, в итоге вы получите что-то вроде этого:

GET

Cache cache = CacheManager.getInstance().getCache(CACHE_NAME);
Element elem = cache.get(identifier);
if (elem == null) 
{
   throw new SessionNotFoundException(identifier);
}
if (elem.isExpired())
{
   throw new SessionExpiredException(identifier);  
}

return elem.getObjectValue();

PUT

Cache cache = CacheManager.getInstance().getCache(CACHE_NAME);
// We use ttl = 0 and tti=<ttlInMinutes>, because session timeout is based on session idle timout.
element = new Element(identifier, new SessionElement(), Boolean.FALSE, (int) (timeToLive / VALUE_MS), 0);
cache.put(element);
...