溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring Cloud中Hystrix的請求緩存怎么實現(xiàn)

發(fā)布時間:2021-12-07 11:55:37 來源:億速云 閱讀:139 作者:iii 欄目:大數(shù)據(jù)

本篇內(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í)行效果如下:

Spring Cloud中Hystrix的請求緩存怎么實現(xiàn)  

小伙伴們看到,上面是服務(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é)果,如下:

Spring Cloud中Hystrix的請求緩存怎么實現(xiàn)  

小伙伴們看到,此時服務(wù)提供者的方法執(zhí)行了兩次,因為我在第一次請求結(jié)束后將id為1的緩存清除了。

通過注解開啟緩存

當(dāng)然,我們也可以通過注解來開啟緩存,和緩存相關(guān)的注解一共有三個,分別是@CacheResult、@CacheKey和@CacheRemove,我們分別來看。

@CacheResult

@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ī)則失效。

@CacheKey

當(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,則后者失效。

@CacheRemove

這個當(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ì)量的實用文章!

向AI問一下細(xì)節(jié)

免責(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)容。

AI