SpringCloud - 服务容错保护组件Hystrix的使用详解6(请求缓存)
作者:hangge | 2020-07-17 08:10
六、请求缓存
1,基本介绍
(1)当系统用户不断增长时,每个微服务需要承受的并发压力也越来越大。在分布式环境下,通常压力来自于对依赖服务的调用,因为请求依赖服务的资源需要通过通信来实现,这样的依赖方式比起进程内的调用方式会引起一部分的性能损失,同时 HTTP 相比于其他高性能的通信协议在速度上没有任何优势,所以它有些类似于对数据库这样的外部资源进行读写操作,在高并发的情况下可能会成为系统的瓶颈。(2)Hystrix 中提供了请求缓存的功能,我们可以方便地开启和使用请求缓存来优化系统,达到减轻高并发时的请求线程消耗、降低请求响应时间的效果。具体好处如下:
- 减少重复的请求数,降低依赖服务的并发数。
- 在同一请求的上下文中,相同依赖服务的返回数据始终保持一致。
- 请求缓存在 run() 和 construct() 执行之前生效,所以可以有效减少不必要的线程开销。
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 生成规则,具体有如下两种方式:
(1)下面是使用 cacheKeyMethod 方法的示例,通过在命令请求的同一个类中定义一个专门生成 Key 的方法,并在 @CacheResult 注解的 cacheKeyMethod 方法来指定它即可。
- 使用 @CacheResult 和 @CacheRemove 注解的 cacheKeyMethod 方法来指定具体的生成函数
- 使用 @CahceKey 注解在方法参数中指定用于组装缓存 Key 的元素
@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); } }
- 注意: @CahceKey 注解除了可以指定方法的参数作为缓存 Key 之外,还允许访问参数对象的内部属性作为缓存 Key。比如下面样例,指定了 User 对象的 id 属性作为缓存 Key:
@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)