SpringCould-降级
系统负载过⾼,突发流量或者⽹络等各种异常情况介绍,常⽤的解决⽅案
1、熔断:
保险丝,熔断服务,为了防⽌整个系统故障,包含⼦和下游服务
下单服务 -》商品服务
-》⽤户服务 (出现异常-》熔断)
2、降级:
抛弃⼀些⾮核⼼的接⼝和数据
旅⾏箱的例⼦:只带核⼼的物品,抛弃⾮核⼼的,等有条件的时候再去携带这些物品
3、熔断和降级互相交集
相同点:
1)从可⽤性和可靠性触发,为了防⽌系统崩溃
2)最终让⽤户体验到的是某些功能暂时不能⽤
不同点
1)服务熔断⼀般是下游服务故障导致的,⽽服务降级⼀般是从整体系统负荷考虑,由调⽤⽅
控制
增加的pom.xml
<!--feign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--hystrix依赖,主要是用 @HystrixCommand -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--springboot整合redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
启动类添加注解
@EnableCircuitBreaker
package com.sxpcwlkj.order_server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
public class OrderServerApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServerApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
controller 服务降级
http://localhost:8781/api/v1/order/selectByIdTwo?id=1
@Autowired
private StringRedisTemplate redisTemplate;
/**
*
* @param id
* @return Feign 方式请求
*/
@GetMapping("selectByIdTwo")
@HystrixCommand(fallbackMethod = "saveOrderFail")
public JsonResultObject selectByIdTwi(int id, HttpServletRequest request){
try {
return orderService.selectById(id);
}catch (Exception e){
e.printStackTrace();
logger.error(e.getMessage());
return JsonResultObject.getErroeResult(e.getMessage());
}
}
//注意,方法签名一定要要和api方法一致
private JsonResultObject saveOrderFail(int id, HttpServletRequest request){
//监控报警
String saveOrderKye = "save-order";
String sendValue = redisTemplate.opsForValue().get(saveOrderKye);
final String ip = request.getRemoteAddr();
new Thread( ()->{
if (StringUtils.isBlank(sendValue)) {
System.out.println("紧急短信,用户下单失败,请离开查找原因,ip地址是="+ip);
//发送一个http请求,调用短信服务 TODO
redisTemplate.opsForValue().set(saveOrderKye, "save-order-fail", 20, TimeUnit.SECONDS);
}else{
System.out.println("已经发送过短信,20秒内不重复发送");
}
}).start();
return JsonResultObject.getErroeResult("抢购人数太多,您被挤出来了,稍等重试");
}
案例1:模拟请求超时
接口方法添加注解 @HystrixCommand(fallbackMethod = “saveOrderFail”)
创建一个方法捕获的方法上加上注解
saveOrderFail (注意,方法签名一定要要和api方法一致)
当请异常时,会走此方法