本文我们来演示下Hystrix中解决雪崩效应的第二种方式缓存的实现
Hystrix 为了降低访问服务的频率,支持将一个请求与返回结果做缓存处理。如果再次请求的 URL 没有变化,那么 Hystrix 不会请求服务,而是直接从缓存中将结果返回。这样可以大大降低访问服务的压力。 Hystrix 自带缓存。有两个缺点:
所以我们使用spring的cache。
redis的安装参考此文:https://blog.csdn.net/qq_38526573/article/details/86777528 启动redis服务。
创建一个SpringCloud项目。
添加Hystrix和redis相关的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在application.properties中添加redis的相关配置
spring.application.name=eureka-ribbon-consumer-cache
server.port=9091
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://dpb:123456@eureka1:8761/eureka/,http://dpb:123456@eureka2:8761/eureka/
# Redis
spring.redis.database=0
#Redis 服务器地址
spring.redis.host=192.168.88.150
#Redis 服务器连接端口
spring.redis.port=6379
#Redis 服务器连接密码(默认为空)
spring.redis.password=
#连接池最大连接数(负值表示没有限制)
spring.redis.pool.max-active=100
#连接池最大阻塞等待时间(负值表示没有限制)
spring.redis.pool.max-wait=3000
#连接池最大空闭连接数
spring.redis.pool.max-idle=200
#连接汉最小空闲连接数
spring.redis.pool.min-idle=50
#连接超时时间(毫秒)
spring.redis.pool.timeout=600
添加@EnableCaching 注解放开缓存
@EnableCaching // 开启缓存
@EnableEurekaClient
@SpringBootApplication
public class SpringcloudEurekaConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudEurekaConsumerApplication.class, args);
}
}
service中添加对应的处理方法
@CacheConfig(cacheNames={"com.bobo.shop"})
@Service
public class UserService {
/**
* ribbon 负载均衡
* LoadBalancerClient 通过服务名称可以获取对应的服务的相关信息 ip port等
*/
@Autowired
private LoadBalancerClient loadBalancerClient;
@HystrixCommand(fallbackMethod = "fallBack")
public List<User> getUsers(){
// ServiceInstance 封装的有服务的基本信息 IP和端口等
ServiceInstance si = this.loadBalancerClient.choose("eureka-ribbon-provider");
StringBuilder sb = new StringBuilder();
sb.append("http://")
.append(si.getHost())
.append(":")
.append(si.getPort())
.append("/user");
System.out.println("服务地址:"+sb.toString());
// SpringMVC RestTemplate
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference<List<User>> type = new ParameterizedTypeReference<List<User>>() {};
// ResponseEntity:封装了返回值的信息
ResponseEntity<List<User>> response = rt.exchange(sb.toString(), HttpMethod.GET,null,type);
List<User> list = response.getBody();
return list;
}
/**
* 服务降级
* 返回托底数据的方法
* @return
*/
public List<User> fallBack(){
List<User> list = new ArrayList<>();
list.add(new User(3,"我是托底数据",22));
return list;
}
/**
* 根据用户id查询
* @param id
* @return
*/
@Cacheable(key="'user' + #id")
public User getUserById(Integer id){
System.out.println("*******查询*************:"+id);
return new User(id,"缓存测试数据",20);
}
/**
* 根据用户id删除数据
* @CacheEvict 清除缓存
* @param id
*/
@CacheEvict(key="'user' + #id")
public void deleteUserById(Integer id){
System.out.println("------删除-----:"+id);
}
}
@Cacheable:添加缓存 @CacheEvict:删除缓存
同时注意此注解
同时controller中添加对应的调用方法
@RequestMapping(value="/get",method= RequestMethod.GET)
public User get(Integer id){
return this.userService.getUserById(id);
}
@RequestMapping(value="/del",method=RequestMethod.GET)
public void del(Integer id){
this.userService.deleteUserById(id);
}
启动consumer服务,分别访问请求,查看效果
User类需要序列化,然后重启再访问,第一次访问
同时查看redis中数据
有了缓存数据,第二次访问id为22的数据就会从缓存中取数据了,这个效果自行演示。调用del方法会将我们的缓存删除。