美文网首页
Spring Cloud Hystrix 怎么实现请求缓存

Spring Cloud Hystrix 怎么实现请求缓存

作者: zbsong | 来源:发表于2020-03-24 17:40 被阅读0次

在分布式环境下,通常压力来自于对依赖服务的调用,因为请求依赖服务的资源需要通过通信实现,这样的依赖方式比起进程内的调用会方式会引起一部分的性能损失,同事HTTP相比于其它高性能的通信协议在速度是没有任何优势,所以它有些类似于对数据库这样的外部资源进行读写操作,在高并发情况下可能会成为系统的瓶颈。

在高并发的场景之下,Hystrix提供了请求缓存功能,我们可以方便的开启和使用请求缓存来优化系统,达到减轻高并发时的请求线程消耗、降低请求响应时间的效果。

开启缓存方式

1.在HystrixCommand、HystrixObservableCommand实现的Hystrix命令中重载getCacheKey()方法来开启请求缓存,该方法不能返回null,返回null不会开启请求缓存功能。
2、使用@CacheResult注解开启请求缓存

实现

新建消费者服务实例
  • 创建一个新的Spring Boot工程,命名为:hystrix-cache(随意)
  • 编辑pom.xml,主要依赖如下:
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  • 修改application.yml
spring:
  application:
    name: hystrix-cache
server:
  port: 8000
eureka:
  client:
    service-url:
      defaultZone: http://peer1:1111/eureka/
  • 编辑应用主类
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class HystrixApplication {

    @Bean
    //开启负载均衡
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(HystrixApplication.class, args);
    }

}
  • 编写controller类
@RestController
@RequestMapping(value = "/cache")
public class CacheController {

    @Autowired
    private CacheService cacheService;

    @GetMapping(path = "/test")
    public String testCache() {
        HystrixRequestContext.initializeContext();
        //第一次会远程调用查询数据,后边两次会查询缓存
        cacheService.getUserById("1");
        cacheService.getUserById("1");
        //删除缓存
        cacheService.update("1");
        //再次查询,第一次会再次远程调用获取数据,后边两次直接查询缓存
        cacheService.getUserById("1");
        cacheService.getUserById("1");
        cacheService.getUserById("2");
        cacheService.getUserById("2");
        return "请求成功";
    }
}
  • 编写service类
@Service
public class CacheService {

    @Autowired
    RestTemplate restTemplate;

    //@CacheResult 用来标记请求命令返回结果应该被缓存
    //cacheKeyMethod指定key的函数,Key的生成函数
    @CacheResult(cacheKeyMethod = "getCacheKey")
    @HystrixCommand(fallbackMethod = "error")
    public String getUserById(String id) {
        return restTemplate.getForObject("http://hello-client/cache/getUserById?id={1}", String.class,id);
    }

    //用来让缓存失效,失效的缓存根据定义的key决定
    //@CacheRemove注解有commandKey、cacheKeyMethod两个参数
    //commandKey属性是必须要指定的,它用来指明需要使用请求缓存的请求命令,只有配置了该属性,Hystrix才能找到正确的请求命令缓存位置。
    @CacheRemove(commandKey = "getUserById")
    public String update(String id) {
        return restTemplate.postForObject("http://hello-client/cache/updateUserById?id={id}", null, String.class,id);
    }

    public String getCacheKey(String id) {
        //使用ID作为缓存的key
        return id;
    }

    public String error(String id) {
        return "出错啦出错啦";
    }
}
修改服务提供者服务实例
  • 添加controller
@RestController
@RequestMapping(value = "/cache")
public class CacheController {

    @RequestMapping(value = "/getUserById")
    public String getUserById(String id) {
        System.out.println("处理消费者请求--获取用户:" + id);
        return id;
    }

    @PostMapping(value = "/updateUserById")
    public String updateUserById(String id) {
        System.out.println("处理消费者请求--更新用户:" + id);
        return id;
    }

}

测试

1、启动注册中心、启动服务提供实例、启动刚刚创建的工程

2、分析:
通过刚刚消费者服务新建的controller里面的调用逻辑来看,如果缓存生效的话,应该是下面的执行情况:
1.使用参数“1”发送请求,会远程调用获取数据
2.再次使用参数“1”发送请求,直接从缓存中获取数据
3.然后是清除key为“1”的缓存
4.再次使用参数“1”发送请求,应该会重新执行远程调用获取数据
5.再次使用参数“1”发送请求,直接从缓存中获取数据
6.使用参数“2”发送请求,会远程调用获取数据
7.再次使用参数“2”发送请求,直接从缓存中获取数据
服务提供者实例应该会收到三个请求,下面我们来验证一下
访问http://localhost:8000/cache/test

image.png
从服务提供者控制台打印可以看到结果和我们上面分析的一致。

使用@CacheKey注解实现请求缓存更简单,但是使用@CacheKey注解的时候需要注意,它的优先级比cacheKeyMethod的优先级低,如果已经使用了cacheKeyMethod指定缓存Key的生成函数,那么@CacheKey注解不会生效,示例如下:

@CacheResult
@HystrixCommand(fallbackMethod = "error")
public String getUserById(@CacheKey("id") String id) {
    return restTemplate.getForObject("http://hello-client/cache/getUserById?id={1}", String.class,id);
}

相关文章

网友评论

      本文标题:Spring Cloud Hystrix 怎么实现请求缓存

      本文链接:https://www.haomeiwen.com/subject/awgoyhtx.html