查找是否开启了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; }
} |