查找是否開啓了request cache,是否有請求緩存,如果有緩存,直接取用緩存,返回結果
6.1 reqeust context請求上下文概念
首先,有一個概念,叫做reqeust context,請求上下文。一般來說,在一個web應用中reqeust context(請求上下文),在一個web應用中,Hystrix會在一個filter裏面,對每一個請求都施加一個請求上下文,例如 tomcat容器內,每一次請求,就是一次請求上下文,然後在這一次請求上下文中,我們會去執行N多代碼,調用N多依賴服務,有的依賴服務可能還會調用好幾次,在一次請求上下文中,如果有多個command,參數都是一樣的,調用的接口也是一樣的,其實結果可以認爲也是一樣的;那麼這個時候,我們就可以讓第一次command執行,返回的結果,被緩存在內存中,然後這個請求上下文中,後續的其他對這個依賴的調用全部從內存中取用緩存結果就可以了
不用在一次請求上下文中反覆多次的執行一樣的command,提升整個請求的性能。
6.2 初始化一個request context
一般來說,在java web來的應用中,都是通過filter過濾器來實現的
HystrixCommand和HystrixObservableCommand都可以指定一個緩存key,然後hystrix會自動進行緩存,接着在同一個request context內,再次訪問的時候,就會直接取用緩存
用請求緩存,可以避免重複執行網絡請求
多次調用一個command,那麼只會執行一次,後面都是直接取緩存
對於請求緩存(request caching),請求合併(request collapsing),請求日誌(request log),等等技術,都必須自己管理HystrixReuqestContext的聲明週期
在一個請求執行之前,都必須先初始化一個request context
HystrixRequestContext context = HystrixRequestContext.initializeContext();
然後在請求結束之後,需要關閉request context
context.shutdown();
/** * hystrix請求上下文過濾器,請求緩存 * @author Administrator * */ 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() {
} }
|
6.3 註冊HystrixRequestContextFilter過濾器
@Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new HystrixRequestContextFilter()); filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } |
6.4 request cache的在Command中的實現
一次請求,就是一次request context,對相同的查詢只能執行一次,其餘的都走request cache。
在一次請求上下文中,如果有多個command,參數都是一樣的,調用的接口也是一樣的.那麼這個時候,我們就可以讓第一次command執行,返回的結果,被緩存在內存中,然後這個請求上下文中,,後續的其他對這個依賴的調用全部從內存中取用緩存結果
/** * HystrixCommand和HystrixObservableCommand都可以指定一個緩存key, * 然後hystrix會自動進行緩存,接着在同一個request context內,再次訪問的時候,就會直接取用緩存用請求緩存, * 可以避免重複執行網絡請求 */ @Override protected String getCacheKey() { return "joint_examWholeAnalysis_" + associatedId; } |
一個批量查詢數據的接口
/** * 總分分析:request cache * 在一次請求上下文中,如果有多個command,參數都是一樣的,調用的接口也是一樣的 * 那麼這個時候,我們就可以讓第一次command執行,返回的結果,被緩存在內存中,然後這個請求上下文中, * 後續的其他對這個依賴的調用全部從內存中取用緩存結果 * @param associatedId * @return * @throws ExecutionException * @throws InterruptedException */ @RequestMapping(value="/jointExamWholeAnalysis/associatedIds/{associatedIds}") public String jointExamWholeAnalysisByIds(@PathVariable String associatedIds,HttpServletRequest request) throws InterruptedException, ExecutionException{ String url = SERVICE_IP_PORT + MDJ_API_ASSOCIATED_JOINT_EXAM_WHOLE_ANALYSIS; for (String associatedId:associatedIds.split(",")) { HystrixCommand<String> jointExamWholeAnalysisCommand = new JointExamWholeAnalysisCommand(associatedId, url); String jointExamWholeAnalysis = jointExamWholeAnalysisCommand.execute(); System.out.println(jointExamWholeAnalysis); System.out.println(jointExamWholeAnalysisCommand.isResponseFromCache());
} return "success"; } |
6.5 Hystrix緩存的手動清理
/** * 緩存的手動清理 * @param associatedId */ public static void flushCache(String associatedId) { HystrixRequestCache.getInstance(COMMAND_KEY, HystrixConcurrencyStrategyDefault.getInstance()).clear(associatedId); } |
/** * request cache 手動清除Command * @author mawenbo * */ public class JoinExamWholeAnalysisFlushCacheCommand extends HystrixCommand<Boolean>{
private String associatedId; private static final HystrixCommandKey COMMAND_KEY = HystrixCommandKey.Factory.asKey("jointExamWholeAnalysis");
public JoinExamWholeAnalysisFlushCacheCommand(String associatedId) { super(Setter //CommondGroup:默認情況下,因爲就是通過command group來定義一個線程池的,統計信息,成功次數,[timeout(thread)]超時次數,失敗次數,可以看到某一個服務整體的一些訪問情況 .withGroupKey(HystrixCommandGroupKey.Factory.asKey("AssociatedExamAllCourses")) .andCommandKey(COMMAND_KEY) ); }
@Override protected Boolean run() throws Exception { //執行緩存信息更新,清除緩存 JointExamWholeAnalysisCommand.flushCache(associatedId); return true; }
} |