开发者

WebApp Session Management using Ehcache

开发者 https://www.devze.com 2023-04-11 13:14 出处:网络
In my project I am using ehcache to store loggged in user details and some other information (which app will use this at runtime instead of fetching from db). The following is my ehcache configuration

In my project I am using ehcache to store loggged in user details and some other information (which app will use this at runtime instead of fetching from db). The following is my ehcache configuration:

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

But the problem is most of the time session timeout happening (even user is not inactive more >30). Sometimes its happening for 10 mins,...

All the actions will try to retrieve user object per each request from the ehcache.

I am not 开发者_运维技巧sure how ehcache will determine expiry time.


Ehcache evicts objects from the cache when one of the following conditions are met:

  1. Object has not been accessed from ehcache (read or updated) for more than timeToIdle seconds. This rule does not apply if timeToIdle is not set. In other words, an object is qualified to remain in the cache for infinite time even if it is never accessed (read or updated) from the cache when timeToIdle is not set.

  2. Object has been in the cache for more than timeToLive seconds. This rule does not apply if timeToLive is not set. In other words, an object is qualified to remain in the cache for infinite time.

  3. Number of items in the cache has reached maxElementsInMemory limit. In that case memoryStoreEvictionPolicy comes into action and removes the elements matching the eviction policy until the number of elements in the cache becomes less than maxElementsInMemory limit, even though those items are qualified to be in the cache as per condition No. 1 and No. 2.

Hope that clarifies it!


ehcache does not garantee to keep all your elements for 30 minutes.

In your configuration, you have a maxElementsInMemory of 50000. Maybe you have at one point reached the 50000 and therefore the Least Recently Used entry will get evicted as you have set overflowToDisk to false.


Preamble

I you are planing to use ehCache as a session management implementation first check, if you cannot by any chance use a already provided, and probably better suited session implementation. If you are using a web container or a full fleshed jee server you really should try this first


Why

Okay. You are quite sure to not do it the right easy way. Here are some hints, why you might want to use ehCache for sessions

  1. Your service is not part of a jee server/web container.
  2. Your service is stateless but from time to time, you need states (framework code).
  3. You cannot distinguish calls because of a proxy between you and the distinguishable client, e.g you are some kind of middleware for a service/service which does not provided distinguishable data as default, but uses parameters like userId or sessionId conditionally but not constitutively.
  4. You just did not RTFM and want to do it your way.

For 1 please check, if a web container like jetty is an option. You certainly use web access of the whole session thingy would not pop up for you.

For 2 please check, if Apache Shiro won't do what you want. If not, ehCache could be your friend.

For 3... welcome to the club.

For 4... well I guess if you did not read the manual, you won't read this either.


How to

If you want to implement a session management using ehCache please assure that your data is serializable. This will reduce problems and let you use the sensitive features of ehCache. namely persistence to disk, caching nodes, recover from this, and so on.

Do not use a cache for every session, but one cache for all sessions. The sessionId is the key on your cache, and a values are going to a Map. Do not forget about concurrency (think of ajax calls). It might be best to use the ConcurrentHashMap from java.util.concurrent. But maybe you are Dr Heinz M. Kabutz and find a even cooler way to do it.

I found it very helpfull to rather use size than amount of elements to keep in storage. You might not know, what data/objets are stored later on. Do not forget to set a persistence strategy. I used storing to temp folder here.

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

Because we want to implement a session manager, we do not bother about timeToLiveSeconds. Sessions time out after a certain idle time. So we do not constrain the element to a maximal ttl, but use the timeToIdleSeconds to let an element time out. Do not bother with the timeToIdleSeconds and timeToLiveSeconds because you can set specific values to the elements to add later on.

Eviction

One note on the expiry time. An element in memory will never be evicted because of a configured time. The memory will build up until the defined memory constraint is hit. So if you define 100 elements, if the 101 element is added, the memoryStoreEvictionPolicy will bet triggered and one element will be - in this configuration - flushed to disk (ehCache 2.2). For the disk storage, there will be a thread checking for expiry time (diskExpiryThreadIntervalSeconds). See the documentation. So you have to check the retrieved element from the cache using isExpired() to be sure it has not expired.


So in the end, you will end up with something like this:

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号