Hystrix進階攻略之請求緩存

一、背景

HystrixCommand和HystrixObservableCommand都可以指定一個緩存key,然後hystrix會自動進行緩存,接著在同一個request context內,再次訪問的時候,就會直接取用緩存

用請求緩存,可以避免重複執行網絡請求

多次調用一個command,那麼只會執行一次,後面都是直接取緩存

二、原理介紹

首先,有一個概念,叫做reqeust context,請求上下文,一般來說,在一個web應用中,hystrix

我們會在一個filter裡面,對每一個請求都施加一個請求上下文,就是說,tomcat容器內,每一次請求,就是一次請求上下文

然後在這次請求上下文中,我們會去執行N多代碼,調用N多依賴服務,有的依賴服務可能還會調用好幾次

在一次請求上下文中,如果有多個command,參數都是一樣的,調用的接口也是一樣的,其實結果可以認為也是一樣的

那麼這個時候,我們就可以讓第一次command執行,返回的結果,被緩存在內存中,然後這個請求上下文中,後續的其他對這個依賴的調用全部從內存中取用緩存結果就可以了

不用在一次請求上下文中反覆多次的執行一樣的command,提升整個請求的性能

HystrixCommand和HystrixObservableCommand都可以指定一個緩存key,然後hystrix會自動進行緩存,接著在同一個request context內,再次訪問的時候,就會直接取用緩存

用請求緩存,可以避免重複執行網絡請求

多次調用一個command,那麼只會執行一次,後面都是直接取緩存

對於請求緩存(request caching),請求合併(request collapsing),請求日誌(request log),等等技術,都必須自己管理HystrixReuqestContext的聲明週期

在一個請求執行之前,都必須先初始化一個request context

HystrixRequestContext context = HystrixRequestContext.initializeContext();

然後在請求結束之後,需要關閉request context

context.shutdown();

一般來說,在java web來的應用中,都是通過filter過濾器來實現的

三、核心代碼

1、定義一個過濾器,攔截每一次請求

/**
* hystrix請求上下文過濾器
* @author 極客慧 www.jikeh.cn
*
*/
public class HystrixRequestContextFilter implements Filter {


public void init(FilterConfig config) throws ServletException {

}

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
chain.doFilter(request, response);
} catch (Exception e) {
e.printStackTrace();
} finally {
context.shutdown();
}
}

public void destroy() {

}

}

2、啟動類註冊過濾器

@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(
new HystrixRequestContextFilter());
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}

3、自定義緩存key

Hystrix進階攻略之請求緩存

注意:是沒有默認key的,如果不重寫該方法,也就不能實現緩存功能的

@Override
protected String getCacheKey() {
return "ad_info_" + adId;
}

三、實戰演練

依賴系統:spring-boot-hystrix-ad

代碼下載地址:https://gitee.com/jikeh/JiKeHCN-RELEASE.git

項目名:spring-boot-hystrix-request-cache

1、啟動系統

  • 啟動spring-boot-hystrix-ad
  • 啟動spring-boot-hystrix-request-cache

2、改造下代碼

1)改下我們之前的批量獲取廣告的接口

public List<adinfo> getAdInfos(String adIds) {

List<adinfo> ads = new ArrayList<>();

for(String adId : adIds.split(",")) {
GetAdInfoCommand getAdInfoCommand = new GetAdInfoCommand(
Long.valueOf(adId));
AdInfo adInfo = getAdInfoCommand.execute();
ads.add(adInfo);
System.out.println("是否讀取緩存:"+getAdInfoCommand.isResponseFromCache());
}


return new ArrayList<>(ads);
}
/<adinfo>/<adinfo>

2)打印點東西,看請求緩存是否生效

Hystrix進階攻略之請求緩存

註釋:看是否打印這句話?

打印:沒走緩存

不打印:走緩存

3、請求演練

請求地址:http://localhost:8022/get/ads?adIds=1,1,3,3,5,5

注意:請求緩存指的是hystrix的請求,而不是http的請求;

即:

  • 第一次hystrix請求不走緩存;
  • 第二次hystrix請求才走緩存;

並不是:http請求,切記這一點

4、分析測試結果:

Hystrix進階攻略之請求緩存

同一次http請求中,有6次hystrix請求;

如果不走請求緩存:會6次調用外部系統;

走緩存:會3次調用外部系統;

顯而易見,根據打印結果,只有3次調用外部系統接口==>走了請求緩存,即:緩存生效


分享到:


相關文章: