使用Ehcache的WebApp会话管理

时间:2011-10-09 03:57:40

标签: java session web-applications ehcache session-management

在我的项目中,我使用ehcache存储loggged用户详细信息和一些其他信息(哪个应用程序将在运行时使用它而不是从db获取)。以下是我的ehcache配置:

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

但问题是大多数时间会话超时发生(即使用户不是非活动状态更多&gt; 30)。有时它发生了10分钟,...

所有操作都会尝试根据ehcache的每个请求检索用户对象。

我不确定ehcache将如何确定到期时间。

3 个答案:

答案 0 :(得分:5)

当满足以下条件之一时,Ehcache会从缓存中驱逐对象:

  1. 尚未从ehcache(读取或更新)访问对象的时间超过timeToIdle秒。如果未设置timeToIdle,则此规则不适用。换句话说,即使在未设置timeToIdle的情况下从未从缓存访问(读取或更新)对象,对象也有资格在缓存中保留无限时间。

  2. 对象在缓存中的时间超过timeToLive秒。如果未设置timeToLive,则此规则不适用。换句话说,一个对象有资格在缓存中保留无限时间。

  3. 缓存中的项目数已达到maxElementsInMemory限制。在这种情况下,memoryStoreEvictionPolicy开始执行并删除与驱逐策略匹配的元素,直到缓存中的元素数量变得小于maxElementsInMemory限制,即使这些项目有资格在缓存中按照条件1号和2号。

  4. 希望澄清它!

答案 1 :(得分:1)

ehcache不保证将所有元素保留30分钟。

在你的配置中,你有一个50000的maxElementsInMemory。也许你已经达到了50000,因此你将overflowToDisk设置为false,因此最近最少使用的条目将被驱逐。

答案 2 :(得分:0)

<强>序言

我计划首先使用ehCache作为会话管理实现进行检查,如果你不能使用已经提供的,可能更适合的会话实现。如果您使用的是网络容器或完整的肉食服务器,那么您真的应该先尝试一下


<强>为什么

好。你很确定不能以正确的方式做到这一点。以下是一些提示,为什么您可能希望将ehCache用于会话

  1. 您的服务不属于jee服务器/网络容器。
  2. 您的服务是无状态的,但有时您需要状态(框架代码)。
  3. 由于您和可区分客户之间的代理,您无法区分呼叫,例如,您是某种服务/服务的中间件,它不提供默认的可区分数据,但有条件地使用userId或sessionId等参数但不是组成性的
  4. 你刚才没有RTFM而且想按照自己的方式去做。
  5. 对于1,请检查是否可以选择像jetty这样的Web容器。你肯定会使用整个会话的网页访问,不会为你弹出。

    对于2,请检查,如果Apache Shiro不符合您的要求。如果没有,ehCache可能是你的朋友。

    3 ...欢迎来到俱乐部。

    对于4 ...好吧,如果你没有看过这本手册,你也不会读这篇文章。


    如何

    如果您想使用ehCache实现会话管理,请确保您的数据是可序列化的。这将减少问题,让您使用ehCache的敏感功能。即持久化到磁盘,缓存节点,从中恢复,等等。

    为每个会话使用缓存,但一个缓存用于所有会话。 sessionId是缓存中的关键字,值为Map。不要忘记并发性(想想ajax调用)。最好使用ConcurrentHashMap中的java.util.concurrent。但也许你是Dr Heinz M. Kabutz并找到一种更酷的方法来做到这一点。

    我发现使用大小比保存数量的元素更有帮助。您可能不知道,以后会存储哪些数据/对象。不要忘记设置持久性策略。我在这里使用存储到临时文件夹。

    <?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让元素超时。 请勿使用timeToIdleSecondstimeToLiveSeconds,因为您可以为要稍后添加的元素设置特定值。

    <强>逐出

    关于到期时间的一个注释。由于配置的时间,内存中的元素永远不会被驱逐。内存将累积,直到命中定义的内存约束。因此,如果您定义了100个元素,如果添加了101元素,则memoryStoreEvictionPolicy将被触发,并且在此配置中,一个元素将被刷新到磁盘(ehCache 2.2)。对于磁盘存储,将有一个线程检查到期时间(diskExpiryThreadIntervalSeconds)。请参阅documentation。 因此,您必须使用isExpired()从缓存中检查检索到的元素,以确保它未过期。


    所以最后,你最终会得到这样的东西:

    获取

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