10

我有一个简单的 Grails 应用程序,需要在用户会话期间(在使用界面时)多次定期调用外部 Web 服务。

我想缓存这个 Web 服务响应,但是服务的结果每隔几天就会改变一次,所以我想把它缓存一小段时间(也许每天刷新)。

Grails 缓存插件似乎不支持“生存时间”实现,所以我一直在探索一些可能的解决方案。我想知道什么插件或程序解决方案最能解决这个问题。

例子:

BuildConfig.groovy

plugins{
    compile ':cache:1.0.0'
}

MyController.groovy

def getItems(){
    def items = MyService.getItems()
    [items: items]
}

MyService.groovy

@Cacheable("itemsCache")
class MyService {
    def getItems() {
        def results

        //expensive external web service call

        return results
    }
}

更新

有很多不错的选择。我决定采用 Burt 建议的插件方法。我已经包含了一个示例答案,对上面的代码示例进行了微小的更改,以帮助其他想要做类似事情的人。此配置会在 24 小时后使缓存过期。

BuildConfig.groovy

plugins{
    compile ':cache:1.1.7'
    compile ':cache-ehcache:1.0.1'
}

配置文件

grails.cache.config = {
    defaultCache {
        maxElementsInMemory 10000
        eternal false
        timeToIdleSeconds 86400
        timeToLiveSeconds 86400
        overflowToDisk false
        maxElementsOnDisk 0
        diskPersistent false
        diskExpiryThreadIntervalSeconds 120
        memoryStoreEvictionPolicy 'LRU'
     }
 }
4

4 回答 4

12

核心插件不支持 TTL,但 Ehcache 插件支持。请参阅http://grails-plugins.github.com/grails-cache-ehcache/docs/manual/guide/usage.html#dsl

http://grails.org/plugin/cache-ehcache插件依赖于http://grails.org/plugin/cache但用一个使用 Ehcache 的缓存管理器替换了缓存管理器(所以你需要安装两者)

于 2013-02-13T03:09:04.417 回答
1

破解/解决方法是使用@Cacheable("itemsCache") 和@CacheFlush("itemsCache") 的组合。

告诉 getItems() 方法缓存结果。

@Cacheable("itemsCache")
def getItems() {
}

然后是另一个刷新缓存的服务方法,您可以从作业中频繁调用它。

@CacheFlush("itemsCache")
def flushItemsCache() {}
于 2013-02-13T05:57:42.057 回答
0

grails-cache单元测试(查找 timeToLiveSeconds)中,我看到您可以在缓存级别配置缓存,而不是每个方法调用或类似的配置。使用此方法,您将配置grails.cache.config的设置。

您将使用您的生存时间设置创建一个专用缓存,然后在您的服务中引用它。

于 2013-02-12T20:35:11.503 回答
0

在与SpEL的战斗中失败了几个小时后,我最终赢得了战争!如您所知,Grails 缓存没有开箱即用的 TTL。您可以坚持使用 ehcache 并进行一些花哨的配置。或者更糟糕的是在保存/更新等时添加逻辑刷新它。但我的解决方案是:

@Cacheable(value = 'domainInstance', key="#someId.concat((new java.util.GregorianCalendar().getTimeInMillis()/10000))")
def getSomeStuffOfDb(String someId){
         //extract something of db
  }       
}

还有一件事要指出。您可以跳过 Config.groovy 中的配置,它将自动创建和添加。但是,如果您的应用程序在启动后立即处于负载状态,则会导致一些异常。

    2017-03-02 14:05:53,159 [http-apr-8080-exec-169] ERROR errors.GrailsExceptionResolver  - CacheException occurred when processing request: [GET] /some/get
Failed to get lock for campaignInstance cache creation. Stacktrace follows:

所以为避免这种情况,请添加配置,以便事先准备好缓存设施。

grails.cache.enabled = true
grails.cache.clearAtStartup = true
grails.cache.config = {
    defaults {
        maxElementsInMemory 10000
        overflowToDisk false
    }
    cache {
        name 'domainInstance'
    }
}

GregorianCalendar().getTimeInMillis()/10000 将使 TTL 约为 10 秒。/1000 ~1 秒。纯数学在这里。

于 2017-03-03T10:07:56.800 回答