为什么ehcache不传播过期事件?

时间:2014-10-10 15:26:49

标签: rmi ehcache

为什么ehcache不传播到期事件?你是如何处理它的?

这是我的情况。我有两个节点使用RMI相互同步。我的配置如下:

<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties="peerDiscovery=manual, rmiUrls=//localhost:51001/sessionCache|//localhost:51002/sessionCache"/>

<cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
                                 properties="hostName=0.0.0.0, port=51002, socketTimeoutMillis=2000"/>

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

<cache name="sessionCache"
       maxEntriesLocalHeap="20000"
       maxEntriesLocalDisk="100000"
       eternal="false"
       diskSpoolBufferSizeMB="20"
       timeToIdleSeconds="60"
       memoryStoreEvictionPolicy="LRU"
       transactionalMode="off">

    <persistence strategy="localTempSwap"/>
    <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" properties="replicateAsynchronously=true" />
    <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
            properties="bootstrapAsynchronously=false"
            propertySeparator=","/>
</cache>

现在想象以下情景:

  1. 对服务器A的登录调用会创建放入复制缓存的会话。
  2. 连续调用服务器A以从缓存中获取会话对象将重置timeToIdleSeconds计数器。
  3. 继续调用服务器A 65秒,以确保服务器B上的会话将在步骤1中将会话对象放入缓存后从未调用过。
  4. 呼叫服务器B.在内部,它会从本地缓存中删除会话对象 ,并会调用RegisteredEventListeners.internalNotifyElementExpiry,最终会调用RMISynchronousCacheReplicator.notifyElementExpired
  5. 在第4步中,我希望服务器B将RmiEventType.REMOVE发送到服务器A.而RMISynchronousCacheReplicator.notifyElementExpired有以下正文

    public final void notifyElementExpired(final Ehcache cache, final Element element) {
        /*do not propagate expiries. The element should expire in the remote cache at the same time, thus
          preseerving coherency.
          */
    }
    

    看起来RMICacheReplicatorFactory的创建者从未考虑过timeToIdleSeconds驱逐算法。

    是否在每个cache.replace()之后立即手动调用cache.get()来重置群集中的TTI(timeToIdle)?

    cache.remove() notifyElementExpired的额外cacheEventListener是否只能从群集中删除已过期的元素?

1 个答案:

答案 0 :(得分:0)

好吧,我最终搞黑了。如果有更优雅的解决方案,请告诉我们。

我创建了另外的缓存事件监听器,看起来像这样

class MyCacheEventListener(properties: Properties) extends CacheEventListener {

  override def notifyElementExpired(cache: Ehcache, element: Element): Unit = {

    cache.getCacheEventNotificationService.notifyElementRemoved(element, false)
  }

  override def notifyElementRemoved(cache: Ehcache, element: Element): Unit = {}
  override def notifyElementEvicted(cache: Ehcache, element: Element): Unit = {}
  override def notifyRemoveAll(cache: Ehcache): Unit = {}
  override def notifyElementPut(cache: Ehcache, element: Element): Unit = {}
  override def notifyElementUpdated(cache: Ehcache, element: Element): Unit = {}
  override def dispose(): Unit = {}
}

负责将假RmiEventType.REMOVE发送到群集。它在config

中使用范围local指定
<cacheEventListenerFactory class="com.zzzz.MyCacheEventListenerFactory" listenFor="local" />

为了刷新我必须在成功cache.get()

之后执行此操作
cache.getCacheEventNotificationService.notifyElementUpdated(element, false)

它很难看但不确定我还能做些什么。坦率地说,我认为Terracotta可以在RMICacheReplicatorFactory中轻松实现它。