您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“Spring Cloud中Hystrix的請求緩存怎么實現(xiàn)”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
如果我們使用了自定義Hystrix請求命令的方式來使用Hystrix,那么我們只需要重寫getCacheKey方法即可實現(xiàn)請求緩存,如下:
public class BookCommand extends HystrixCommand<Book> { private RestTemplate restTemplate; private Long id; @Override protected Book getFallback() { Throwable executionException = getExecutionException(); System.out.println(executionException.getMessage()); return new Book("宋詩選注", 88, "錢鐘書", "三聯(lián)書店"); } @Override protected Book run() throws Exception { return restTemplate.getForObject("http://HELLO-SERVICE/getbook5/{1}", Book.class,id); } public BookCommand(Setter setter, RestTemplate restTemplate,Long id) { super(setter); this.restTemplate = restTemplate; this.id = id; } @Override protected String getCacheKey() { return String.valueOf(id); } }
系統(tǒng)在運(yùn)行時會根據(jù)getCacheKey方法的返回值來判斷這個請求是否和之前執(zhí)行過的請求一樣,即被緩存,如果被緩存,則直接使用緩存數(shù)據(jù)而不去請求服務(wù)提供者,那么很明顯,getCacheKey方法將在run方法之前執(zhí)行。我現(xiàn)在在服務(wù)提供者中打印一個日志,如下:
@RequestMapping(value = "/getbook5/{id}", method = RequestMethod.GET) public Book book5(@PathVariable("id") Integer id) { System.out.println(">>>>>>>>/getbook5/{id}"); if (id == 1) { return new Book("《李自成》", 55, "姚雪垠", "人民文學(xué)出版社"); } else if (id == 2) { return new Book("中國文學(xué)簡史", 33, "林庚", "清華大學(xué)出版社"); } return new Book("文學(xué)改良芻議", 33, "胡適", "無"); }
然后我們服務(wù)消費者的Controller中來執(zhí)行這個請求,如下:
@RequestMapping("/test5") public Book test5() { HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey("commandKey"); HystrixRequestContext.initializeContext(); BookCommand bc1 = new BookCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")).andCommandKey(commandKey), restTemplate, 1l); Book e1 = bc1.execute(); BookCommand bc2 = new BookCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")).andCommandKey(commandKey), restTemplate, 1l); Book e2 = bc2.execute(); BookCommand bc3 = new BookCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")).andCommandKey(commandKey), restTemplate, 1l); Book e3 = bc3.execute(); System.out.println("e1:" + e1); System.out.println("e2:" + e2); System.out.println("e3:" + e3); return e1; }
我連著發(fā)起三個相同的請求,我們來看看服務(wù)提供者的日志打印情況,注意,在服務(wù)請求發(fā)起之前,需要先初始化HystrixRequestContext。執(zhí)行效果如下:
小伙伴們看到,上面是服務(wù)提供者打印出來的日志,下面是服務(wù)消費者打印出來的日志,發(fā)起了三個請求,但是服務(wù)提供者實際上只執(zhí)行了一次,其他兩次都使用了緩存數(shù)據(jù)。
有一種特殊的情況:如果我將服務(wù)提供者的數(shù)據(jù)修改了,那么緩存的數(shù)據(jù)就應(yīng)該被清除,否則用戶在讀取的時候就有可能獲取到一個錯誤的數(shù)據(jù),緩存數(shù)據(jù)的清除也很容易,也是根據(jù)id來清除,方式如下:
@RequestMapping("/test5") public Book test5() { HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey("commandKey"); HystrixRequestContext.initializeContext(); BookCommand bc1 = new BookCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")).andCommandKey(commandKey), restTemplate, 1l); Book e1 = bc1.execute(); HystrixRequestCache.getInstance(commandKey, HystrixConcurrencyStrategyDefault.getInstance()).clear(String.valueOf(1l)); BookCommand bc2 = new BookCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")).andCommandKey(commandKey), restTemplate, 1l); Book e2 = bc2.execute(); BookCommand bc3 = new BookCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")).andCommandKey(commandKey), restTemplate, 1l); Book e3 = bc3.execute(); System.out.println("e1:" + e1); System.out.println("e2:" + e2); System.out.println("e3:" + e3); return e1; }
小伙伴們注意,這里我們執(zhí)行完第一次請求之后,id為1的數(shù)據(jù)就已經(jīng)被緩存下來了,然后我通過HystrixRequestCache中的clear方法將緩存的數(shù)據(jù)清除掉,這個時候如果我再發(fā)起請求,則又會調(diào)用服務(wù)提供者的方法,我們來看一下執(zhí)行結(jié)果,如下:
小伙伴們看到,此時服務(wù)提供者的方法執(zhí)行了兩次,因為我在第一次請求結(jié)束后將id為1的緩存清除了。
當(dāng)然,我們也可以通過注解來開啟緩存,和緩存相關(guān)的注解一共有三個,分別是@CacheResult、@CacheKey和@CacheRemove,我們分別來看。
@CacheResult方法可以用在我們之前的Service方法上,表示給該方法開啟緩存,默認(rèn)情況下方法的所有參數(shù)都將作為緩存的key,如下:
@CacheResult @HystrixCommand public Book test6(Integer id,String aa) { return restTemplate.getForObject("http://HELLO-SERVICE/getbook5/{1}", Book.class, id); }
此時test6方法會自動開啟緩存,默認(rèn)所有的參數(shù)都將作為緩存的key,如果在某次調(diào)用中傳入的兩個參數(shù)和之前傳入的兩個參數(shù)都一致的話,則直接使用緩存,否則就發(fā)起請求,如下:
@RequestMapping("/test6") public Book test6() { HystrixRequestContext.initializeContext(); //第一次發(fā)起請求 Book b1 = bookService.test6(2, ""); //參數(shù)和上次一致,使用緩存數(shù)據(jù) Book b2 = bookService.test6(2, ""); //參數(shù)不一致,發(fā)起新請求 Book b3 = bookService.test6(2, "aa"); return b1; }
當(dāng)然這里我們也可以在@CacheResult中添加cacheKeyMethod屬性來指定返回緩存key的方法,注意返回的key要是String類型的,如下:
@CacheResult(cacheKeyMethod = "getCacheKey2") @HystrixCommand public Book test6(Integer id) { return restTemplate.getForObject("http://HELLO-SERVICE/getbook5/{1}", Book.class, id); } public String getCacheKey2(Integer id) { return String.valueOf(id); }
此時默認(rèn)的規(guī)則失效。
當(dāng)然除了使用默認(rèn)數(shù)據(jù)之外,我們也可以使用@CacheKey來指定緩存的key,如下:
@CacheResult @HystrixCommand public Book test6(@CacheKey Integer id,String aa) { return restTemplate.getForObject("http://HELLO-SERVICE/getbook5/{1}", Book.class, id); }
這里我們使用@CacheKey注解指明了緩存的key為id,和aa這個參數(shù)無關(guān),此時只要id相同就認(rèn)為是同一個請求,而aa參數(shù)的值則不會作為判斷緩存的依據(jù)(這里只是舉例子,實際開發(fā)中我們的調(diào)用條件可能都要作為key,否則可能會獲取到錯誤的數(shù)據(jù))。如果我們即使用了@CacheResult中cacheKeyMethod屬性來指定key,又使用了@CacheKey注解來指定key,則后者失效。
這個當(dāng)然是用來讓緩存失效的注解,用法也很簡單,如下:
@CacheRemove(commandKey = "test6") @HystrixCommand public Book test7(@CacheKey Integer id) { return null; }
注意這里必須指定commandKey,commandKey的值就為緩存的位置,配置了commandKey屬性的值,Hystrix才能找到請求命令緩存的位置。舉個簡單的例子,如下:
@RequestMapping("/test6") public Book test6() { HystrixRequestContext.initializeContext(); //第一次發(fā)起請求 Book b1 = bookService.test6(2); //清除緩存 bookService.test7(2); //緩存被清除,重新發(fā)起請求 Book b2 = bookService.test6(2); //參數(shù)一致,使用緩存數(shù)據(jù) Book b3 = bookService.test6(2); return b1; }
“Spring Cloud中Hystrix的請求緩存怎么實現(xiàn)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。