WebApp Session Management Using Ehcache

In my project, I use ehcache to store the user details and some other information (which application will use this at runtime instead of retrieving from db). The following is the configuration of my ehcache:

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

But the problem is that most of the time the session is waiting for the session (even the user is not inactive for more than 30). Sometimes this happens within 10 minutes ...

All actions will try to get a custom object for each request from ehcache.

I'm not sure how ehcache will determine the expiration time.

+6
source share
3 answers

Ehcache issues objects from the cache when one of the following conditions is true:

  • The object was not accessible from ehcache (read or updated) in more than timeToIdle seconds. This rule does not apply if timeToIdle not set. In other words, an object has the right to remain in the cache for infinite time, even if it never accesses (read or update) from the cache when timeToIdle not set.

  • The object was cached in more than timeToLive seconds. This rule does not apply if timeToLive not set. In other words, an object has the right to remain in the cache for infinite time.

  • The number of items in the cache has reached the limit of maxElementsInMemory . In this case, the memoryStoreEvictionPolicy takes effect and deletes the elements corresponding to the eviction policy until the number of elements in the cache is less than the maxElementsInMemory limit, even if these elements are qualified to be in the cache according to condition No. 1 and No. 2.

Hope this clears up!

+5
source

ehcache does not guarantee that all of your items will be retained for 30 minutes.

In your configuration, you have maxElementsInMemory of 50,000. You may have reached 50,000 at some point, and therefore the β€œLeast Recent Used” element will be displayed because you set overflowToDisk to false.

+1
source

Preamble

I plan to use ehCache as the first session control check if you cannot use an already provided and probably better suitable session. If you use a web container or a full-featured jee server, you really should try this first


Why

Good. You are sure that you will not do it right. Here are some tips why you can use ehCache for sessions.

  • Your service is not part of the jee server / web container.
  • Your service does not have a status, but from time to time you need states (frame code).
  • You cannot distinguish between proxy server calls between you and the distinguished client, for example, you are a kind of middleware for a service / service that does not provide distinguishable data by default, but uses parameters like userId or sessionId, conditionally but not constitutively.
  • You just did not do RTFM and want to do it your own way.

For 1, please check if the web container is suitable, for example, a berth. You, of course, use web access for the entire session, which would not appear for you.

For 2, please check if Apache Shiro will not do what you want. If not, ehCache may be your friend.

For 3 ... welcome to the club.

For 4 ... well, I think if you have not read the manual, you will not read it either.


how

If you want to implement session management with ehCache, make sure your data is serializable. This will reduce problems and allow you to use the sensitive features of ehCache. namely, saving to disk, caching nodes, recovering from this, etc.

Use not a cache for each session, but one for all sessions. sessionId is the key in your cache, and the values ​​are Map . Don't forget about concurrency (think about ajax calls). It is best to use ConcurrentHashMap from java.util.concurrent . But perhaps you are Dr Heinz M. Kabutz and find an even colder way to do this.

I found it very useful to use a size other than the number of items to store. You may not know what data / objects will be stored later. Remember to set a conservation strategy. Here I used save in temp folder.

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

Since we want to implement a session manager, we are not worried about timeToLiveSeconds . Sessions time out after a certain downtime. Therefore, we do not limit the element to the maximum ttl, but use timeToIdleSeconds to allow the element to time out. Don't worry about timeToIdleSeconds and timeToLiveSeconds , because you can set specific values ​​for items that need to be added later.

Eviction

One note about expiration time. An item in memory will never be displayed due to the time set. The memory will increase until a certain memory limit is set. Therefore, if you define 100 elements, if 101 element is added, memoryStoreEvictionPolicy will bet, and one element will be flushed to disk (in this configuration) (ehCache 2.2). For disk storage, the thread will be checked for expiration time ( diskExpiryThreadIntervalSeconds ). See the documentation . Therefore, you should check the extracted item from the cache using isExpired() so that it does not expire.


So, in the end you will get 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
source

Source: https://habr.com/ru/post/898912/


All Articles