返回 导航

SpringBoot / Cloud

hangge.com

SpringCloud - 服务容错保护组件Hystrix的使用详解6(请求缓存)

作者:hangge | 2020-07-17 08:10

六、请求缓存

1,基本介绍

(1)当系统用户不断增长时,每个微服务需要承受的并发压力也越来越大。在分布式环境下,通常压力来自于对依赖服务的调用,因为请求依赖服务的资源需要通过通信来实现,这样的依赖方式比起进程内的调用方式会引起一部分的性能损失,同时 HTTP 相比于其他高性能的通信协议在速度上没有任何优势,所以它有些类似于对数据库这样的外部资源进行读写操作,在高并发的情况下可能会成为系统的瓶颈。
(2)Hystrix 中提供了请求缓存的功能,我们可以方便地开启和使用请求缓存来优化系统,达到减轻高并发时的请求线程消耗、降低请求响应时间的效果。具体好处如下:

2,开启请求缓存功能

Hystrix 不需要独立外置的缓存系统来支持,只需要添加 @CacheResult 注解即可为请求命令开启缓存功能:
注意:如果没有指定缓存 Key,默认它的缓存 Key 值会使用所有的参数。比如下面样例即为 Long 类型的 id 值。
@Service
public class UserService {
    @Autowired
    RestTemplate restTemplate;

    @CacheResult
    @HystrixCommand()
    public User getUserById(Long id) {
        return restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class, id);
    }
}

3,定义缓存 Key

缓存除了使用默认 Key 值外(使用所有参数),我们也可以为请求命令指定具体的缓存 Key 生成规则,具体有如下两种方式:
  • 使用 @CacheResult @CacheRemove 注解的 cacheKeyMethod 方法来指定具体的生成函数
  • 使用 @CahceKey 注解在方法参数中指定用于组装缓存 Key 的元素
(1)下面是使用 cacheKeyMethod 方法的示例,通过在命令请求的同一个类中定义一个专门生成 Key 的方法,并在 @CacheResult 注解的 cacheKeyMethod 方法来指定它即可。
@Service
public class UserService {
    @Autowired
    RestTemplate restTemplate;

    @CacheResult(cacheKeyMethod = "getUserByIdCacheKey")
    @HystrixCommand()
    public User getUserById(Long id) {
        return restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class, id);
    }

    private Long getUserByIdCacheKey(Long id) {
        return id;
    }
}

(2)下面使用 @CahceKey 注解的样例,它可以给请求命令的参数上标记,使其作为缓存的 Key 值:
注意@CahceKey 注解的优先级比 cacheKeyMethod 的优先级低,如果已经使用了 cacheKeyMethod 指定缓存 Key 的生成函数,那么 @CacheKey 注解不会生效。
@Service
public class UserService {
    @Autowired
    RestTemplate restTemplate;

    @CacheResult
    @HystrixCommand()
    public User getUserById(@CacheKey("id") Long id) {
        return restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class, id);
    }
}
@Service
public class UserService {
    @Autowired
    RestTemplate restTemplate;

    @CacheResult
    @HystrixCommand()
    public User getUserById(@CacheKey("id") User user) {
        return restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class,
                user.getId());
    }
}

4,清理失效缓存

    如果请求命令中还有更新数据的写操作,那么缓存中的数据就需要我们在进行写操作时进行及时处理,以防止读操作的请求命令获取到了失效的数据。通过 Hystrix @CacheRemove 注解可以实现失效缓存的清理:
注意@CacheRemove 注解的 commandKey 属性是必须要指定的它用来指明需要使用请求缓存的请求命令,只有通过该属性的配置,Hystrix 才能找到正确的请求命令缓存位置。
@Service
public class UserService {
    @Autowired
    RestTemplate restTemplate;

    @CacheResult
    @HystrixCommand
    public User getUserById(@CacheKey("id") User user) {
        return restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class,
                user.getId());
    }

    @CacheRemove(commandKey = "getUserById")
    @HystrixCommand
    public void getUserById(@CacheKey("id") User user) {
        return restTemplate.postForObject("http://USER-SERVICE/users/{1}", user,
                User.class);
    }
}
评论

全部评论(0)

回到顶部