一个接口对外提供服务,在某些特殊的场景下需要服务降级,这些场景包括:
1)当前服务响应太慢,超过某个时间的限制后
2)当前服务出现了异常
所谓的降级就是出现这些异常的时候,需要用另外一个方法来处理这些异常,最后用正确的方式对外。所以这里的降级和系统全局异常处理是两个概念,这里降级后对外就是一个正常的返回。
1.依赖,其中eureka-client是因为一般这样的服务需要在微服务体系中,所以加上它
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.配置
server:
port: 8005
spring:
application:
name: cloud-payment-hystrix-service
eureka:
client:
#false 表示是否将自己注册金eureka 默认true
register-with-eureka: true
#false 表示是否让eureka服务端抓取自己的注册信息,默认是true,集群必须设置为true 才能配合ribbon负载均衡
fetch-registry: true
service-url:
#设置与eureka 交互的地址查询服务 和注册服务都需要依赖这个地址
defaultZone: http://localhost:7001/eureka
3-1)接下来的部分就需要区分是服务的生产者还是消费者,如果这个服务是生产者,那么一般它不需要用的feign,那么它的启动类如下,且配置就是第2点的配置就好了
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class HystrixMain8005 {
public static void main(String[] args) {
SpringApplication.run(HystrixMain8005.class,args);
}
}
3-2)如果这个服务是消费者,也就是该服务中用到了feign,那么它的启动类如下
@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class HystrixOrderMain7006 {
public static void main(String[] args) {
SpringApplication.run(HystrixOrderMain7006.class,args);
}
}
且配置中增加
feign:
hystrix:
enabled: true
4.单个方法的降级
1)系统异常的降级
@HystrixCommand(fallbackMethod = "paymentTimeoutHandler")
public String paymentTimeout(String id){
int value = 19/0;
return "线程池"+Thread.currentThread().getName()+"paymentTimeout 调用成功";
}
//服务降级,超时或者异常才产生降级,且超时是可配置的
//参数不可少,不然系统认为找不到降级方法
public String paymentTimeoutHandler(String id){
return "8005调用超时或者系统异常";
}
注意降级方法的参数一定要和原有的方法一致,不然降级出现异常
2)系统响应超时的降级,这种里面同时包含了系统异常的降级,这里的超时时间配置的是5秒
@HystrixCommand(fallbackMethod = "paymentTimeoutHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "5000")
})
public String paymentTimeout(String id){
int timeout = 3000;
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
//int value = 19/0;
return "线程池"+Thread.currentThread().getName()+"paymentTimeout"+id+"超时"+timeout+"秒";
}
//服务降级,超时或者异常才产生降级,且超时是可配置的
//参数不可少,不然系统认为找不到降级方法
public String paymentTimeoutHandler(String id){
return "8005调用超时或者系统异常";
}
5.全局的降级配置
单个方法的降级当数量多了以后配置起来麻烦,这时候可以配置一个全局降级处理
1)把配置转移到类上
@Component
@DefaultProperties(defaultFallback = "overallHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "2000")
})
public class PaymentService {
2)方法上的注解换成不带参数的
@HystrixCommand
public String paymentTimeout2(String id){
int timeout = 3000;
//int index = 10/0;
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池"+Thread.currentThread().getName()+"paymentTimeout"+id+"超时"+timeout/1000+"秒";
}
3)添加全局配置的降级处理方法
public String overallHandler(){
return "这里是全局超时或者异常处理";
}
注意点:
-1)全局降级配置在类上,它的生效范围就是当前类上,我想应该有整个系统的配置,有时间可以去研究下
-2)全局的降级处理类overallHandler这个方法不需要带参数,这点和单个方法降级处理不一样
6.针对消费者使用feign的情况时,对feignClient下的所有接口做统一降级处理
这种情况就和前两种不一样,不需要用前两种的知识,只需要我们创建一个类去实现feignClient对应接口
@Component
@FeignClient(value = "CLOUD-PAYMENT-HYSTRIX-SERVICE",fallback = HystrixPaymentFallbackService.class)
public interface HystrixPaymentService {
@GetMapping("hystrix/paymentOk/{id}")
String paymentOk(@PathVariable("id") String id);
@GetMapping("hystrix/paymentTimeout/{id}")
public String paymentTimeout(@PathVariable("id") String id);
}
@Component
public class HystrixPaymentFallbackService implements HystrixPaymentService{
@Override
public String paymentOk(String id) {
return "CLOUD-PAYMENT-HYSTRIX-SERVICE paymentOk 调用异常";
}
@Override
public String paymentTimeout(String id) {
return "CLOUD-PAYMENT-HYSTRIX-SERVICE paymentTimeout 调用异常";
}
}
这里说明下,3种情况会触发到降级里面
1)服务的生产者宕机
2)服务的生产者调用出现异常
3)调用超时,这里的超时是根据配置来看的,没有配置的话,默认一秒,配置如下
ribbon: ReadTimeout: 2000 ConnectTimeout: 2000
最后总结下:
1.不管是消费者还是生产者,都可以对自己的服务进行降级处理
2.对于使用feign去调用别人的时候,降级处理方式有些不一样(启动类,配置)
原文:https://www.cnblogs.com/johnzhao/p/14586424.html