通过实现HystrixCommand或者HystrixObservableCommand的getCacheKey方法,可以启动缓存。

  1. public class CommandUsingRequestCache extends HystrixCommand<Boolean> {
  2. private final int value;
  3. protected CommandUsingRequestCache(int value) {
  4. super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
  5. this.value = value;
  6. }
  7. @Override
  8. protected Boolean run() {
  9. return value == 0 || value % 2 == 0;
  10. }
  11. @Override
  12. protected String getCacheKey() {
  13. return String.valueOf(value);
  14. }
  15. }

执行命令

  1. @Test
  2. public void testWithoutCacheHits() {
  3. HystrixRequestContext context = HystrixRequestContext.initializeContext();
  4. try {
  5. assertTrue(new CommandUsingRequestCache(2).execute());
  6. assertFalse(new CommandUsingRequestCache(1).execute());
  7. assertTrue(new CommandUsingRequestCache(0).execute());
  8. assertTrue(new CommandUsingRequestCache(58672).execute());
  9. } finally {
  10. context.shutdown();
  11. }
  12. }

  Hystrix通过getCacheKey方法来获取缓存中的值,缓存值的生命周期为一个请求。

  本质上,在toObservable方法中,在执行前添加了从缓存中获取缓存的逻辑,在执行后,将返回结果存入缓存的逻辑。

  1. public Observable<R> toObservable() {
  2. ...
  3. return Observable.defer(new Func0<Observable<R>>() {
  4. @Override
  5. public Observable<R> call() {
  6. ...
  7. final boolean requestCacheEnabled = isRequestCachingEnabled();
  8. final String cacheKey = getCacheKey();
  9. if (requestCacheEnabled) {
  10. HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.get(cacheKey);
  11. if (fromCache != null) {
  12. isResponseFromCache = true;
  13. return handleRequestCacheHitAndEmitValues(fromCache, _cmd);
  14. }
  15. }
  16. Observable<R> hystrixObservable =
  17. Observable.defer(applyHystrixSemantics)
  18. .map(wrapWithAllOnNextHooks);
  19. Observable<R> afterCache;
  20. if (requestCacheEnabled && cacheKey != null) {
  21. HystrixCachedObservable<R> toCache = HystrixCachedObservable.from(hystrixObservable, _cmd);
  22. HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.putIfAbsent(cacheKey, toCache);
  23. ...
  24. } else {
  25. afterCache = hystrixObservable;
  26. }
  27. ...
  28. }
  29. });
  30. }

  HystrixCachedObservable内部使用type(命令类型:HystrixCommandKey为1,HystrixCollapserKey为2),commandKey的name,HystrixConcurrencyStrategy作为缓存的key  

  1. private static class RequestCacheKey {
  2. private final short type;
  3. private final String key;
  4. private final HystrixConcurrencyStrategy concurrencyStrategy;
  5. ...

  6. private static class ValueCacheKey {
  7. private final RequestCacheKey rvKey;
  8. private final String valueCacheKey;
  9. ...
  10. }

  HystrixCachedObservable的值存储一个Observable,并且通过HystrixCachedObservable进行封装。

  1. protected HystrixCachedObservable(final Observable<R> originalObservable) {
  2. ReplaySubject<R> replaySubject = ReplaySubject.create();
  3. this.originalSubscription = originalObservable
  4. .subscribe(replaySubject);
  5.  
  6. this.cachedObservable = replaySubject
  7. .doOnUnsubscribe(new Action0() {
  8. @Override
  9. public void call() {
  10. outstandingSubscriptions--;
  11. if (outstandingSubscriptions == 0) {
  12. originalSubscription.unsubscribe();
  13. }
  14. }
  15. })
  16. .doOnSubscribe(new Action0() {
  17. @Override
  18. public void call() {
  19. outstandingSubscriptions++;
  20. }
  21. });
  22. }

  HystrixCachedObservable内部使用一个Map作为缓存, 这个Map存储在一个HystrixRequestVariableHolder中,所以它的生命周期为一个请求内部。

  1. private static final HystrixRequestVariableHolder<ConcurrentHashMap<ValueCacheKey, HystrixCachedObservable<?>>> requestVariableForCache = new HystrixRequestVariableHolder<ConcurrentHashMap<ValueCacheKey, HystrixCachedObservable<?>>>(new HystrixRequestVariableLifecycle<ConcurrentHashMap<ValueCacheKey, HystrixCachedObservable<?>>>();
  1. <T> HystrixCachedObservable<T> get(String cacheKey) {
  2. ValueCacheKey key = getRequestCacheKey(cacheKey);
  3. if (key != null) {
  4. ConcurrentHashMap<ValueCacheKey, HystrixCachedObservable<?>> cacheInstance = requestVariableForCache.get(concurrencyStrategy);
  5. if (cacheInstance == null) {
  6. throw new IllegalStateException("Request caching is not available. Maybe you need to initialize the HystrixRequestContext?");
  7. }
  8. /* look for the stored value */
  9. return (HystrixCachedObservable<T>) cacheInstance.get(key);
  10. }
  11. return null;
  12. }

如果异常 是否也缓存?

  是的,fallback的异常也会被缓存下来。

缓存的有效范围?

  为同一个请求内。

hystrix总结之缓存的更多相关文章

  1. 笔记:Spring Cloud Hystrix 异常处理、缓存和请求合并

    异常处理 在 HystrixCommand 实现的run方法中抛出异常,除了 HystrixBadRequestException之外,其他异常均会被Hystrix 认为命令执行失败并触发服务降级处理 ...

  2. 服务容错保护断路器Hystrix之六:缓存功能的使用

    高并发环境下如果能处理好缓存就可以有效的减小服务器的压力,Java中有许多非常好用的缓存工具,比如Redis.EHCache等,当然在Spring Cloud的Hystrix中也提供了请求缓存的功能, ...

  3. Hystrix框架5--请求缓存和collapser

    简介 在Hystrix中有个Request的概念,有一些操作需要在request中进行 缓存 在Hystrix调用服务时,如果只是查询接口,可以使用缓存进行优化,从而跳过真实访问请求. 应用 需要启用 ...

  4. Spring-cloud (八) Hystrix 请求缓存的使用

    前言: 最近忙着微服务项目的开发,脱更了半个月多,今天项目的初版已经完成,所以打算继续我们的微服务学习,由于Hystrix这一块东西好多,只好多拆分几篇文章写,对于一般对性能要求不是很高的项目中,可以 ...

  5. 服务容错保护断路器Hystrix之七:做到自动降级

    从<高可用服务设计之二:Rate limiting 限流与降级>中的“自动降级”中,我们这边将系统遇到“危险”时采取的整套应急方案和措施统一称为降级或服务降级.想要帮助服务做到自动降级,需 ...

  6. 断路器Hystrix与Turbine集群监控-Spring Cloud学习第三天(非原创)

    文章大纲 一.Hystrix基础介绍二.断路器Hystrix简单使用三.自定义Hystrix请求命令四.Hystrix的服务降级与异常处理五.Hystrix的请求缓存与请求合并六.Hystrix仪表盘 ...

  7. Spring Cloud 之 Hystrix.

    一.概述  在微服务架构中,我们将系统拆分成了很多服务单元,各单元的应用间通过服务注册与订阅的方式互相依赖.由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依 ...

  8. 服务容错保护hystrix

    灾难性雪崩效应 如何解决灾难性雪崩效应 降级 超时降级.资源不足时(线程或信号量)降级,降级后可以配合降级接口返回托底数据.实现一个 fallback 方法, 当请求后端服务出现异常的时候, 可以使用 ...

  9. Hystrix原理与实战(转)

    背景 分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务.如下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商品服 ...

随机推荐

  1. 如何校验内存数据的一致性,DynamicExpresso 算是帮上大忙了

    一:背景 1. 讲故事 记的在上一家公司做全内存项目的时候,因为一些关键表会在程序 startup 的时候全量灌入到内存中,但随着时间的推移,内存和数据库的同步偶尔会出现数据差异的情况,伴随着就是运营 ...

  2. Hitool打开出现failed to create the java virtual machine

    今天在安装Hitool后,打开hitool后出现了错误:failed to create the java virtual machine. 解决方法如下: 记事本打开HiTool.ini -star ...

  3. Mybatis入门(一)------基本概念操作

    Mybatis简介 Mybatis是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置 ...

  4. undertow配置

    # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 # 不要设置过大,如果过大,启动项目会报错:打开文件数过多 #server.undertow.io- ...

  5. 区块链入门到实战(27)之以太坊(Ethereum) – 智能合约开发

    智能合约的优点 与传统合同相比,智能合约有一些显著优点: 不需要中间人 费用低 代码就是规则 区块链网络中有多个备份,不用担心丢失 避免人工错误 无需信任,就可履行协议 匿名履行协议 以太坊(Ethe ...

  6. Qt setMouseTracking使用

    Qt setMouseTracking使用(转载)   bool mouseTracking 这个属性保存的是窗口部件跟踪鼠标是否生效. 如果鼠标跟踪失效(默认),当鼠标被移动的时候只有在至少一个鼠标 ...

  7. Laravel Pipeline原理及使用

    Laravel Pipeline原理及使用 开发中可能遇到非常冗长的逻辑,以至于我们想将针对性逻辑拆分出来,但是又拿不准该如何拆分才能实现较高的扩展性并保证较高的维护性,或者说不知道如何优雅的将待处理 ...

  8. P4609 建筑师

    题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 n 个建筑,每个建筑的高度是 1 到 n 之间的一个整数. 小 Z 有很严重的强迫症,他不喜欢有两个建筑的高度相同. ...

  9. 跨平台C# UI库

    https://github.com/AvaloniaUI/Avalonia https://www.cnblogs.com/leolion/p/7144896.html https://github ...

  10. Motion Matching 资料汇总

    https://www.gdcvault.com/play/1023280/Motion-Matching-and-The-Road https://twvideo01.ubm-us.net/o1/v ...