2013-02-12 5 views
10

ユーザーのセッション中に(インターフェイスを使用している間に)外部Webサービスへの定期的な呼び出しを行う必要がある単純なGrailsアプリケーションがあります。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 
    } 
} 

UPDATE

多くの良いオプションがありました。私は、バルト氏が提案したプラグインのアプローチを採用することに決めました。私は上記のコード例のマイナーな変更を加えたサンプル回答を含めて、他の人が似たようなことをしたいときに役立てています。この構成では、24時間後にキャッシュが失効します。

BuildConfig.groovy

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

Config.groovygrails-cacheユニットテスト(timeToLiveSecondsを探してください)、私はあなたがキャッシュ・レベルでのキャッシングを構成することができていることがわかりから

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

最新のキャッシュプラグインを使用すると、期限切れになることはありません: "このプラグインを使用して"有効期限 "を設定する方法はないので、キャッシュされたアイテムはタイムアウトがなく、JVMが再起動するまたは@CacheEvictで注釈を付けられたメソッドやアクションをプログラムで呼び出すことによって)キャッシュが部分的または完全にクリアされていることを確認します。 – Gregg

+0

つまり、@CacheEvictを使用するWebサービスにヒットするcronジョブを持つことができます。それは、少なくとも、回避策です。 – Gregg

+1

はい、私はそのアプローチを考えました。さらに進歩を遂げるために、Quartzはcronの代わりにアプリケーション内のすべてを保持することができます。私は、キャッシュプラグインがスプリングキャッシュプラグインのようにもっとうまく動作することを願っています。 – arcdegree

答えて

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のを使用するもので、キャッシュ・マネージャを置き換え

+0

の両方がインストールされている必要があります。 – sanya

0

メソッド呼び出しやそれに類するものではありません。この方法を使用して、grails.cache.configの設定を構成します。

生存時間設定で専用のキャッシュを作成し、それをサービスで参照します。

+0

はい、これは私が見つけた方法の1つですが、このプラグインは推奨されていません。ドキュメントから: "このプラグインはもはや維持されておらず、SpringSourceが開発しサポートしているCacheプラグインに取って代わりました。" – arcdegree

+0

私はテストがテストの一部としてサポートされていない設定を実際に設定していると思います。 –

1

ハック/回避策は@Cacheableの組み合わせを使用することです(「itemsCache」(あなたが両方インストールする必要が) )と@CacheFlush( "itemsCache")です。

getItems()メソッドに結果をキャッシュするように指示します。

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

そして、ジョブから頻繁に呼び出すことができるキャッシュをフラッシュする別のサービス方法です。

@CacheFlush("itemsCache") 
def flushItemsCache() {} 
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秒。純粋な数学はここにあります。

関連する問題