SpringCloud Hystrix服务降级与熔断

Hystrix是什么?

在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。

Hystrix解决了什么问题

复杂分布式体系结构中的应用程序有许多依赖项,每个依赖项在某些时候都不可避免地会失败。如果主机应用程序没有与这些外部故障隔离,那么它有可能被他们拖垮。
例如,对于一个依赖于30个服务的应用程序,每个服务都有99.99%的正常运行时间,你可以期望如下: 99.9930 = 99.7% 可用
也就是说一亿个请求的0.03% = 3000000 会失败
如果一切正常,那么每个月有2个小时服务是不可用的
现实通常是更糟糕

服务降级

什么是服务降级?当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。

  1. pom
<!--hystrix-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--eureka client-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--openfeign-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. yaml
server:
  port: 80

spring:
  application:
    name: cloud-hystrix-consumer
#将服务注册到eureka
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:7001/eureka/
feign:
  hystrix:
    enabled: true
  1. 主启动类加@EnableHystrix注解
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
public class HystrixConsumerMain {
    public static void main(String[] args) {
        SpringApplication.run(HystrixConsumerMain.class,args);
    }
}
  1. ConsumerService接口(Feign接口+注解实现服务接口调用)
@Component
@FeignClient(value = "CLOUD-HYSTRIX-PROVIDER") //调用服务提供方8001
public interface ConsumerService {
	//请求会立即返回结果
    @GetMapping(value = "/hystrix/provider/ok")
    public String  provider_OK();
    //请求会延迟3秒返回结果
    @GetMapping(value = "/hystrix/provider/timeout")
    public String  provider_TimeOut();
}

8001服务提供方ProviderService.java相应代码

/**
* 正常
* @return
*/
public String provider_OK() {
   return "线程池:" + Thread.currentThread().getName() + " provider_OK" + "\t" ;
}
/**
 * 超时
 * @return
 */
public String provider_TimeOut() {
    try {
        TimeUnit.MILLISECONDS.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "线程池:" + Thread.currentThread().getName() + " 3秒provider_TimeOut"  + "\t" ;
}
  1. ConsumerController
@RestController
@Slf4j
public class ConsumerController {
    @Resource
    private ConsumerService consumerService;

    @GetMapping(value = "/hystrix/consumer/ok")
    public String  consumer_OK(){
        return consumerService.provider_OK();
    }

    @GetMapping(value = "/hystrix/consumer/timeout")
    public String  consumer_TimeOut(){
        try {
        }catch (Exception e){
            e.printStackTrace();
        };
        return consumerService.provider_TimeOut();
    }
}
  1. 使用Jmeter进行压力测试
    来20000个并发压死8001服务提供方,20000个请求都去访问provider_TimeOut服务
    在这里插入图片描述
    在这里插入图片描述
    浏览器访问provider_OK服务也会出现延迟响应,正常情况不会出现延迟(http://localhost:8001/hystrix/provider/ok)
    浏览器访问consumer_OK偶尔会出现超时报错(http://localhost/hystrix/consumer/ok)

OpenFeign默认等待一秒钟,超时就会报错

  1. 服务降级
  • 第一种:一个方法一个fallbackMethod处理
@GetMapping(value = "/hystrix/consumer/timeout")
@HystrixCommand(fallbackMethod = "consumerTimeOutFallbackMethod",
commandProperties = {@HystrixProperty(name= HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS,value = "2000")})//两秒超时
public String  consumer_TimeOut() {
    return consumerService.provider_TimeOut();
}

public String consumerTimeOutFallbackMethod() {
    return "80端口请求:请求超时或者自己运行出错!";
}
  • 第二种:一个类一个统一fallbackMethod处理
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "commonFallbackMethod")
public class ConsumerController {
    @Resource
    private ConsumerService consumerService;

    @HystrixCommand
    @GetMapping(value = "/hystrix/consumer/ok")
    public String  consumer_OK(){
        return consumerService.provider_OK();
    }

    @GetMapping(value = "/hystrix/consumer/timeout")
    @HystrixCommand
    public String  consumer_TimeOut() {
        return consumerService.provider_TimeOut();
    }
    
    public String commonFallbackMethod() {
        return "80端口请求:请求超时或者自己运行出错!公共处理";
    }
  • 第三种:Feign客户端定义的接口添加一个服务降级处理的实现类(可实现业务解耦)
    新建ConsumerFallBackService.java
@Component
public class ConsumerFallBackService implements ConsumerService{
    @Override
    public String provider_OK() {

        return "ConsumerFallBackService-80端口:provider_OK超时或异常";
    }

    @Override
    public String provider_TimeOut() {
        return "ConsumerFallBackService-80端口:provider_TimeOut超时或异常";
    }
}

ConsumerService.java@FeignClient注解增加fallback

@Component
@FeignClient(value = "CLOUD-HYSTRIX-PROVIDER",fallback = ConsumerFallBackService.class)
public interface ConsumerService {

    @GetMapping(value = "/hystrix/provider/ok")
    public String  provider_OK();

    @GetMapping(value = "/hystrix/provider/timeout")
    public String  provider_TimeOut();
}

服务熔断

服务雪崩

多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C有调用其他的微服务,这就是所谓的”扇出”,如扇出的链路上某个微服务的调用响应式过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统雪崩,所谓的”雪崩效应”。

服务熔断: 熔断机制是应对雪崩效应的一种微服务链路保护机制,

当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回”错误”的响应信息。当检测到该节点微服务响应正常后恢复调用链路,在SpringCloud框架机制通过Hystrix实现,Hystrix会监控微服务见调用的状况,当失败的调用到一个阈值,缺省是5秒内20次调用失败就会启动熔断机制,熔断机制的注解是@HystrixCommand

对于熔断机制的实现,Hystrix设计了三种状态:

1.熔断关闭状态(Closed) 服务没有故障时,熔断器所处的状态,对调用方的调用不做任何限制。
2.熔断开启状态(Open) 在固定时间窗口内(Hystrix默认是10秒),接口调用出错比率达到一个阈值(Hystrix默认为50%),会进入熔断开启状态。进入熔断状态后,后续对该服务接口的调用不再经过网络,直接执行本地的fallback方法。
3.半熔断状态(Half-Open)

在进入熔断开启状态一段时间之后(Hystrix默认是5秒),熔断器会进入半熔断状态。所谓半熔断就是尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率。如果成功率达到预期,则说明服务已恢复,进入熔断关闭状态;如果成功率仍旧很低,则重新进入熔断关闭状态。

代码实现

@HystrixCommand(fallbackMethod = "provider_CircuitBreakerFallBack",
commandProperties = {@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ENABLED,value = "true"),
@HystrixProperty(name= HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD,value = "10"),         //熔断触发的最小个数
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS,value = "10000"), //熔断多少秒后去尝试请求
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE,value = "50")       //失败率达到多少百分比后熔断
}
)
public String provider_CircuitBreaker(Integer id) {
    if (id < 0){
        throw new RuntimeException("服务熔断");
    }
    return "线程池:" + Thread.currentThread().getName() + "---provider_CircuitBreaker---"  + "正常返回" ;
}
public String provider_CircuitBreakerFallBack(Integer id){
    return "线程池:" + Thread.currentThread().getName() + "---provider_CircuitBreakerFallBack---"  + "服务熔断" ;
}

测试
id>=0:输出provider_CircuitBreaker方法的返回值
id < 0:输出provider_CircuitBreakerFallBack方法的返回值(fallback方法)

当请求时大于10,并且失败率达到50%,服务熔断开启,输入正值也走fallback方法
服务熔断

十秒之后,进入半熔断状态,如果服务能正常调用,则服务恢复(熔断关闭状态);否则重新进入熔断关闭状态

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值