zoukankan      html  css  js  c++  java
  • Spring Cloud(Dalston.SR5)--Hystrix 断路器-缓存

    在 Spring Cloud 中可以使用注解的方式来支持 Hystrix 的缓存,缓存与合并请求功能需要先初始化请求上下文才能实现,因此,必须实现 javax.servlet.Filter 用于创建和销毁 Hystrix 的请求上下文,而缓存的注解有 @CacheResult、@CacheRemove,@CacheResult 注解必须和 @HystrixCommand 注解一起使用,示例如下:

    • 创建 Filter

      在 Filter 初始化时就创建 HystrixRequestContext,然后在每个请求调用 doFilter 方法时,将初始化的上下文赋值到当前线程存储,这样就能在全局使用 Hystrix 的缓存和合并请求

      package org.lixue;

         

      import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;

         

      import javax.servlet.*;

      import javax.servlet.annotation.WebFilter;

      importj ava.io.IOException;

         

      @WebFilter(urlPatterns="/*",filterName="HystrixRequestContextFilter")

      public class HystrixRequestContextFilter implements Filter{

      HystrixRequestContext context=null;

         

      @Override

      public void init(FilterConfig filterConfig) throws ServletException{

      context=HystrixRequestContext.initializeContext();

      }

         

      @Override

      publicvoid doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException{

      HystrixRequestContext.setContextOnCurrentThread(context);

      try{

      chain.doFilter(request,response);

      }catch(Exceptionex){

      ex.printStackTrace();

      }

      }

         

      @Override

      publicvoiddestroy(){

      if(context!=null){

      context.shutdown();

      }

      }

      }

         

    • 创建服务调用

      注解 @CacheResult 必须和 @HystrixCommand 同时使用,@CacheResult 注解的 cacheKeyMethod 参数指定的方法必须和 @CacheResult 标注的方法参数一致,并且相同参数产生的 key 值应该一致;

      如果数据存在修改,则必须使用 @CacheRemove 注解标注修改方法,同样也需要指定 cacheKeyMethod 参数,表示需要移除缓存的 key,其 commandKey 参数也必须指定和 @HystrixCommand 注解的 commandKey 值一致;

      如果不指定 @CacheResult 和 @CacheRemove 注解的 cacheKeyMethod 参数,也可使用 @CacheKey 注解来标注方法的参数,表示使用方法的参数来作为缓存 key

      package org.lixue;

         

      import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

      import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;

      import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;

      import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;

      import org.springframework.beans.factory.annotation.Autowired;

      import org.springframework.stereotype.Component;

      import org.springframework.web.client.RestTemplate;

         

      @Component

      public class HelloWorldClient{

         

      @Autowired

      private RestTemplate restTemplate;

         

      @HystrixCommand(fallbackMethod="speakFallback",commandKey="hello-world",

      threadPoolKey="hello-world",groupKey="hello-world",

      commandProperties={

      @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="500")

      },

      threadPoolProperties={

      @HystrixProperty(name="coreSize",value="50")

      }

      )

      @CacheResult(cacheKeyMethod="speakCacheKey")

      public String speak(String name){

      if(name==null||"".equals(name)){

      name="null";

      }

      return restTemplate.getForObject("http://HELLOWORLD-PROVIDER/speaks?names="+name,String.class);

      }

         

      /**

      *生成speak方法的缓存Key

      *

      *@param name

      *@return

      */

      private String speakCacheKey(String name){

      return"speak."+name;

      }

         

      /**

      *修改speak数据,移除缓存

      *

      *@param name

      *@return

      */

      @CacheRemove(commandKey="hello-world",cacheKeyMethod="speakCacheKey")

      public String updateSpeak(String name){

      return name;

      }

         

      /**

      *speak返回的回退方法

      *

      *@param name

      *@return

      */

      private String speakFallback(String name){

      return"call error,name is"+name;

      }

      }

    • 服务增加日志

      @RequestMapping(method=RequestMethod.GET,name="speak",path="/speaks",

      produces=MediaType.APPLICATION_JSON_UTF8_VALUE)

      public Map<String,String> speaks(@RequestParam(value="names")String names) throws InterruptedException{

      System.out.println("speaksnames="+names);

      Map<String,String>map=newHashMap<>();

      if(names==null||"".equals(names)){

      return map;

      }

         

      String[] splitName=names.split(",");

      for(Stringname:splitName){

      map.put(name,"HelloWorld"+name+"Port="+port);

      }

      return map;

      }

         

    • 测试验证

      由于我们使用了 Ribbon 因此首先启动 eureka-server 和 service-provider 服务,然后启动该项目,访问 http://localhost:8077/speak?name=abc 可以看到能正常返回信息,如下:

      {"abc":"Hello World abc Port=8002"}

      服务输出日志:

      speaks names=abc

      多次刷新,可以看到服务的日志只显示了一次,表示后续的刷新访问都是使用的 Hystrix 缓存。

         

         

         

  • 相关阅读:
    Python面试
    PyCharm快捷键
    PyCharm安装及使用
    Python环境搭建
    MYSQL的cmake编译单实例安装
    lamp和lnmp环境的搭建
    模拟解决DOS攻击的shell脚本
    责任链模式
    迭代器模式
    备忘录设计模式
  • 原文地址:https://www.cnblogs.com/li3807/p/8916816.html
Copyright © 2011-2022 走看看