【问题标题】:Hystrix Request Caching by ExampleHystrix 请求缓存示例
【发布时间】:2015-01-22 21:17:19
【问题描述】:

我正在尝试弄清楚 Hystrix request caching 的工作原理,但没有关注他们在文档中提供的 wiki 或端到端示例。

基本上我有以下HystrixCommand 子类:

public class GetFizzCommand extends HystrixCommand<Fizz> {
    private Long id;
    private Map<Long,Fizz> fizzCache = new HashMap<Long,Fizz>();

    void doExecute(Long id) {
        this.id = id;
        execute();
    }

    @Override
    public Fizz run() {
        return getFizzSomehow();
    }

    @Override
    public Fizz getFallback() {
        // Consult a cache somehow.
        // Perhaps something like a Map<Long,Fizz> where the 'id' is the key (?)
        // If the 'id' exists in the cache, return it. Otherwise, give up and return
        // NULL.
        fizzCache.get(id);
    }
}

所以我觉得我在这里违背了常规。我相信 Hystrix 提供内置缓存,'cacheKey' 证明了这一点,但我找不到任何工作示例。如果已经提供了开箱即用的东西,我不想在这里重新发明轮子并将缓存构建到我的命令中。

所以我问:Hystrix 的请求缓存是什么样的(确切地说)?如何将条目添加到缓存中?如何/何时刷新缓存?是否可配置(到期时间、最大大小等)?

【问题讨论】:

标签: java caching fault-tolerance hystrix


【解决方案1】:

根据您链接到 here 的文档,

通过在HystrixCommand 对象上实现getCacheKey() 方法来启用请求缓存...

你还没有实现getCacheKey()

@Override
protected String getCacheKey() {
    return String.valueOf(id); // <-- changed from `value` in example
}

那你还需要HystrixRequestContext

HystrixRequestContext context = HystrixRequestContext.initializeContext();

这是(同样,根据文档)

通常,此上下文将通过包装用户请求或其他生命周期钩子的ServletFilter 进行初始化和关闭。

那么我相信您不能像那样更改execute() 的方法签名(doExecute() 不是接口的一部分),而是将参数传递给命令构造函数并请用execute 注释@Override所以如果你忘记了,你会得到一个编译器错误然后

HystrixRequestContext context = HystrixRequestContext.initializeContext();
GetFizzCommand commandA = new GetFizzCommand(2L);
GetFizzCommand commandB = new GetFizzCommand(2L);
Fizz a = commandA.execute(); // <-- should not be cached
Fizz b = commandB.execute(); // <-- should be cached.

【讨论】:

    【解决方案2】:

    您的控制器中需要一个 HystrixRequestContext

    //init
    HystrixRequestContext context = HystrixRequestContext.initializeContext();
    // get cache logic ...
    
    //close
    context.close();
    

    更好的方法是添加一个过滤器类。

    import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    
    @Component
    @WebFilter(urlPatterns = "/*", asyncSupported = true)
    public class HystrixRequestContextFilter implements Filter {
      @Override
      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        try {
          filterChain.doFilter(servletRequest, servletResponse);
        } finally {
          context.close();
        }
      }
    }
    

    【讨论】:

      【解决方案3】:

      如果你使用@HystrixCommand,你可以在方法参数上使用@com.netflix.hystrix.contrib.javanica.cache.annotation.CacheKey来生成请求缓存key,

      @Component
      public class SpringBootMockRemoteService {
      
          @HystrixCommand(fallbackMethod = "fallback")
          public String getRemoteValue(@CacheKey String username) throws InterruptedException {
              Thread.sleep(3_000);
              return "SUCCESS";
          }
      
          String fallback() {
              return "FALLBACK";
          }
      }
      

      请求缓存键将是参数username的值

      【讨论】:

        猜你喜欢
        • 2016-03-25
        • 2018-08-08
        • 2010-10-11
        • 2010-10-13
        • 1970-01-01
        • 1970-01-01
        • 2013-03-02
        • 2015-01-24
        相关资源
        最近更新 更多