Grails

2013-02-12 44 views
10

में महंगे वेब सेवा कॉल को कैश करने की सर्वोत्तम रणनीति मेरे पास एक साधारण Grails एप्लिकेशन है जिसे उपयोगकर्ता के सत्र (इंटरफ़ेस का उपयोग करते समय) के दौरान कई बार बाहरी वेब सेवा पर आवधिक कॉल करने की आवश्यकता होती है।Grails

मैं इस वेब सेवा प्रतिक्रिया को कैश करना चाहता हूं, लेकिन सेवा के परिणाम हर कुछ दिनों में बदलते हैं, इसलिए मैं इसे थोड़े समय के लिए कैश करना चाहता हूं (शायद दैनिक रीफ्रेश)।

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

अद्यतन

वहाँ कई अच्छे विकल्प थे। मैंने प्लगइन दृष्टिकोण के साथ जाने का फैसला किया कि बर्ट ने सुझाव दिया था। मैंने उपरोक्त कोड उदाहरण में मामूली परिवर्तनों के साथ नमूना उत्तर शामिल किया है ताकि दूसरों को कुछ ऐसा करने में मदद मिल सके। यह कॉन्फ़िगरेशन 24 घंटों के बाद कैश की समय सीमा समाप्त हो जाती है।

BuildConfig.groovy

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

Config.groovy

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 का उपयोग करने वाली एक वेब सेवा को हिट करती है। यह कम से कम एक काम है। – Gregg

+1

हां, मैंने उस दृष्टिकोण को माना है। इसे एक कदम आगे बढ़ाने के लिए, क्वार्ट्ज एप्लिकेशन के भीतर सबकुछ रखने के लिए क्रॉन को प्रतिस्थापित कर सकता है। मेरी इच्छा है कि कैश प्लगइन वसंत कैश प्लगइन की तरह काम करता है। – arcdegree

उत्तर

12

कोर प्लगइन टीटीएल का समर्थन नहीं करता है, लेकिन एहैशे प्लगइन करता है। देखें 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 इकाई परीक्षण (timeToLiveSeconds के लिए देखो), मुझे लगता है कि आप कैश स्तर पर कैशिंग कॉन्फ़िगर कर सकते हैं से

, प्रति विधि कॉल या इसी तरह नहीं। इस विधि का उपयोग करके, आप grails.cache.config के लिए सेटिंग कॉन्फ़िगर करेंगे।

आप अपनी टाइम-टू-लाइव सेटिंग्स के साथ एक समर्पित कैश बनाएंगे और फिर इसे अपनी सेवा में संदर्भित करेंगे।

+0

हां, यह एक तरीका है जिसे मैंने पाया है, हालांकि यह प्लगइन बहिष्कृत है। दस्तावेज़ों से: "यह प्लगइन अब बनाए रखा नहीं गया है। इसे कैश प्लगइन द्वारा हटा दिया गया है जिसे स्प्रिंगसोर्स द्वारा विकसित और समर्थित किया गया है।" – arcdegree

+0

मेरा मानना ​​है कि परीक्षण वास्तव में कॉन्फ़िगरेशन सेट कर रहे हैं जो परीक्षण के हिस्से के रूप में समर्थित नहीं है। –

1

एक हैक/वैकल्पिक हल @Cacheable के संयोजन का उपयोग करने के लिए किया जाएगा ("itemsCache") और @ कैशफ्लश ("आइटम कैश")।

परिणामों को कैश करने के लिए getItems() विधि बताएं।

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

और फिर कैश को फ्लश करने के लिए एक और सेवा विधि, जिसे आप अक्सर नौकरी से कॉल कर सकते हैं।

@CacheFlush("itemsCache") 
def flushItemsCache() {} 
0

स्पेल के साथ लड़ाई में विफल होने के कई घंटों के बाद मैंने अंत में युद्ध जीता है! तो जैसा कि आप जानते हैं कि Grails कैश में बॉक्स से बाहर टीटीएल नहीं है। आप 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' 
    } 
} 

ग्रेगोरी कैलेंडर()। GetTimeInMillis()/10000 ~ 10sec टीटीएल कर देगा।/1000 ~ 1 सेकंड। यहां शुद्ध गणित।