1.服务降级的理解
服务器忙,请稍候再试,不让客户端等待并立刻返回一个友好提示
2.哪些情况会触发服务降级
①程序运行异常
②超时自动降级
③服务熔断触发服务降级
④线程池/信号量打满也会导致服务降级
⑤人工降级
3.服务降级的实例
分别准备服务的提供方和服务的调用方
①添加服务降级的依赖
<!--新增hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
②在yml配置文件中进行相应的配置,将微服务注册到注册中心中。
③创建服务的主启动类
④创建相应的业务类代码
4.实例中出现服务降级的情况
①服务的提供方创建相应的业务代码,当请求数量较大时,访问业务层的代码会出现超时等情况
②服务的消费方远程调用服务提供方的方法,服务提供方down机了会导致服务消费方超时
③服务消费方自身出现访问超时的情况
5.解决上述情况的办法
①服务提供方访问超时了,服务消费方不能一直卡死等待,对服务提供方的业务类代码进行服务降级
②服务提供方down机了,服务消费者不能一直卡死等待,进行服务降级
③服务提供方一切正常,服务消费者自己出故障(服务消费方的等待时间小于服务提供方的访问时间),自己进行降级处理
6.服务降级的具体实现
①在服务的提供方进行服务降级
a.设置自身调用超时时间的峰值,峰值内可以正常运行,超过了需要有兜底的方法处理,作服务降级
b.在业务类可能需要进行服务降级的方法上添加@HystrixCommand注解来解决。
注意:该注解@HystrixCommand中的参数的fallbackMethod的方法名和兜底方法的方法名和参数保持一致
//超时降级演示
@HystrixCommand(fallbackMethod = "payment_TimeoutHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000") //5秒钟以内就是正常的业务逻辑
})
@Override
public String payment_Timeout(Integer id) {
//int timeNumber = 3; //小于等于3秒算是正常情况
int timeNumber = 15; //模拟非正常情况
//int i = 1/0 ; //模拟非正常情况
try {
TimeUnit.SECONDS.sleep(timeNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池:"+Thread.currentThread().getName()+" payment_Timeout,id="+id+" \t o(╥﹏╥)o 耗时:"+timeNumber;
}
//兜底方法,上面方法出问题,我来处理,返回一个出错信息
public String payment_TimeoutHandler(Integer id) {
return "线程池:"+Thread.currentThread().getName()+" payment_TimeoutHandler,系统繁忙,请稍后再试\t o(╥﹏╥)o ";
}
c.在主启动类上面添加 @EnableCircuitBreaker注解
②在服务的消费方进行服务降级
a.在yml配置文件中进行服务降级的配置
feign:
hystrix:
enabled: true #如果处理自身的容错就开启。开启方式与生产端不一样。
b.在服务的消费方的主启动类添加@EnableHystrix注解
c.在业务类的controller上进行相应的服务降级操作
//超时降级演示
@HystrixCommand(fallbackMethod = "payment_TimeoutHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")//超过1.5秒就降级自己
})
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
//int age= 1/0;
String result = paymentHystrixService.payment_Timeout(id);
log.info("*******result:"+result);
return result;
}
//兜底方法,上面方法出问题,我来处理,返回一个出错信息
public String payment_TimeoutHandler(Integer id) {
return "我是消费者80,对方支付系统繁忙请10秒后再试。或自己运行出错,请检查自己。";
}
7.以上每个服务降级处理,每个业务方法都对应一个兜底的方法,代码膨胀,代码耦合性高,采用
统一通用处理和自定义独立处理的分开
①在业务的controller上添加@DefaultProperties注解
//@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod") //全局的
②在对应的可能出现超时或者异常的方法上添加 @HystrixCommand注解
import com.atguigu.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod") //全局的
public class OrderHystrixController {
@Resource
private PaymentHystrixService paymentHystrixService;
@GetMapping("/consumer/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id){
String result = paymentHystrixService.paymentInfo_OK(id);
return result;
}
@HystrixCommand
public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
int age = 10/0;
String result = paymentHystrixService.paymentInfo_TimeOut(id);
return result;
}
//兜底方法
public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id){
return "我是消费者80,对付支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,(┬_┬)";
}
//下面是全局fallback方法
public String payment_Global_FallbackMethod(){
return "Global异常处理信息,请稍后再试,(┬_┬)";
}
}
8.以上解决办法会导致业务类代码和服务降级的统一处理方法混合在一起
解决办法:需要在服务消费方的feign客户端定义的接口添加一个服务降级处理的实现类即可实现解耦
a.创建一个实现类实现接口,统一为接口里面的方法进行异常处理
import org.springframework.stereotype.Component;
@Component
public class PaymentFallbackService implements PaymentHystrixService {
@Override
public String paymentInfo_OK(Integer id) {
return "-----PaymentFallbackService fall back-paymentInfo_OK , (┬_┬)";
}
@Override
public String paymentInfo_TimeOut(Integer id) {
return "-----PaymentFallbackService fall back-paymentInfo_TimeOut , (┬_┬)";
}
}
b.在服务消费方的yml的配置文件中进行相应的配置
feign:
hystrix:
enabled: true #如果处理自身的容错就开启。开启方式与生产端不一样。
c.在服务消费方的feign接口的@FeignClient的注解中指定进行服务降级处理的实现类
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)