Request caching is not available. Maybe you need to initialize the HystrixRequestContext?

     在《spring cloud 微服务实战》书中第159页-----请求缓存这一部分,通过继承HystrixCommand的方式实现的命令,开启请求缓存只需通过重载getCacheKey()方法,

@Override
protected String getCacheKey() {//开启请求缓存
    System.out.println("调用getCacheKey");//打印一下什么时候会触发
    return String.valueOf(id);
}

    然后执行

User u=new UserCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(
        HystrixCommandGroupKey.Factory.asKey("")) ,new RestTemplate(),0L).execute();
    报错了:java.util.concurrent.ExecutionException: Observable onError

Caused by: java.lang.IllegalStateException: Request caching is not available. Maybe you need to initialize the HystrixRequestContext?

   

    错误中提示请求缓存不可用,可能必须初始化上下文,所以在执行命令之前先初始化请求上下文:

HystrixRequestContext.initializeContext();//初始化请求上下文

User u=new UserCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(
        HystrixCommandGroupKey.Factory.asKey("")) ,new RestTemplate(),0L).execute();

      当然这只是测试环境下这样初始化,真正的web项目是在filter中进行初始化的(有两种方式:首先都要要实现filter重写其方法,一种是采用注解的方式@WebFilter,别忘了在启动类上添加@ServletComponentScan注解,另一种是Java代码注册的方式会用到FilterRegistrationBean这个类,后面我会给出两种配置方式的链接)。

  

    现在上下文初始化好了,不过这里有一个坑就是我以为缓存对每次request请求都生效(当然前提是没有清除缓存),即我以为每调用一次controller,下一次你再调用这个controller就会从缓存中取,我理解错了,并不是这样的,因为你每请求一次controller就会走一次filter,上下文又会初始化一次,前面缓存的就失效了,又得重新来。所以你要是想测试缓存,你得在一次controller请求中多次调用那个加了缓存的service或HystrixCommand命令,看来hystrix的请求缓存和redis等存储不一样。所以仔细注意书上写的:在同一用户请求的上下文中,相同依赖服务的返回数据始终保持一致。在当次请求内对同一个依赖进行重复调用,只会真实调用一次。在当次请求内数据可以保证一致性。我还是感觉有点鸡肋。


      在重写请求缓存的方法中我打印了一句话,是为了测试是什么时候会调用该方法,结果每次请求都连续打印了两次那句话,之所以打印两次,原因我们可以通过源码AbstractCommand.class类中看到:

boolean requestCacheEnabled = AbstractCommand.this.isRequestCachingEnabled();
String cacheKey = AbstractCommand.this.getCacheKey();
      程序会判断请求缓存是否开启,然后从重写的getCacheKey方法中获取cacheKey,而isRequestCachingEnabled方法内容为:
protected boolean isRequestCachingEnabled() {
    return ((Boolean)this.properties.requestCacheEnabled().get()).booleanValue() && this.getCacheKey() != null;
}
      所以会打印两次那句话。另外采用注解的方式实现缓存,在使用@CacheKey("id")Long id这种方式时,会报这个错误:java.beans.IntrospectionException: Method not found: isId,暂时不知道原因,所以我采用在@CacheResult里面指定cacheKeyMethod的方式来指定CacheKey

   参考博客地址:https://www.bbsmax.com/A/E35pbO8zvX/

                            http://blog.csdn.net/zhuchuangang/article/details/74566185(filter注解配置)

                                              https://juejin.im/entry/58d4d8f5b123db3f6b6485ec

                            http://doc.okbase.net/ningandjin/archive/121278.html

                            http://blog.csdn.net/mzh1992/article/details/53895613(filter Java配置)

                            http://www.jb51.net/article/112001.htm(filter注解配置)

阅读更多
个人分类: spring-cloud
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭