spring cloud hystrix 熔断详解

熔断的意义

在微服务架构中,服务之间相互调用,当有一个服务出错时,会导致依赖它的服务也错误,进而导致整个微服务集群都出现问题,所以采用熔断机制,当服务调用出现错误时,满足熔断策略,调用方主动熔断服务,返回预制的错误信息。

熔断的用法

robbion方式

在启动类上添加注解@EnableCircuitBreaker

ribbon方式是显示的在方法上添加@HystrixCommand注解,表示方法会调用远程方法,远程方法调用失败时,按照注解中的配置进行熔断,比较好理解

 

    @GetMapping("/hello")
    @HystrixCommand(fallbackMethod = "helloFaile")
    public String hello(){
        totle++;
        restTemplate.getForObject("http://APP/app/exception",String.class);
        return totle + ":" + error;
    }
    public String helloFail(){
        error++;
        return totle + ":" + error;
    }

当restTemplate调用失败(超时或者出现异常)时,就会调用helloFail方法进行返回。

fallbackMethod中的参数为失败时回调方法名,helloFail的参数必须和hello方法的参数个数、类型完全一样。

Feign方式

Feign方式是将我们需要调用的远程方法定义到一个接口中,在接口中定义远程服务名,远程url,调用失败时的回调类。在我们的业务代码中需要调用远程方法时,不在像ribbon一样直接通过RestTemplate调用远程方法,而是通过我们自己定义的接口。

  • 启动类上添加@EnabledFeignClients
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
@EnableFeignClients
public class DemoStarter {
    public static void main(String[] args) {
        SpringApplication.run(DemoStarter.class,args);
    }
}
  • 定义一个接口,接口中方法为我们需要调用的远程方法
@FeignClient(name = "app",fallback = RemoteMethodHystrix.class)
public interface IRemoteMethod {
    @GetMapping("/app/exception")
    String hello();
}

@FeignClient注解中name为远程服务名(eureka中注册的服务名),fallback为接口熔断时的回调方法。

方法上@Getmapping中的url为远程服务中提供的接口地址

  • 定义一个接口实现,实现我们定义的IRemoteMethod接口,作为远程接口调用失败时的回调
@Component
public class RemoteMethodHystrix implements IRemoteMethod{
    private int count;
    private int error;
    @Override
    public String hello() {
        return "error:"+(++error);
    }
}
  • 服务调用

我们调用的时候,只需要注入我们定义的接口IRemoteMethod(spring 默认给我做了实现)

@Autowired
    private IRemoteMethod remoteMethod;
@GetMapping("/helloFeign")
    public String helloFeign(){
        String rest = remoteMethod.hello();
        if(rest.startsWith("success")){
            totle++;
            return "totle:"+totle;
        }else{
            return rest;
        }
    }
  • 添加配置

在application.yml中添加开启feign的配置

feign:
  hystrix:
    enabled: true

  熔断验证

验证熔断我们至少需要三个项目,erueka-server,app,demo。app作为服务提供方,demo作为服务调用方。

app提供接口

@GetMapping("/exception")
    public String hello(){
        totle++;
        if(System.currentTimeMillis() % 2 == 0){
            System.out.println(totle + "--"+ error);
            error++;
            Integer.parseInt("a");
        }
        System.out.println(totle + "--"+ error);
        return "success";
    }

我们这里采用随机报异常的方式,当此方法报异常时,会触发服务调用方(demo)的熔断。

当没有配置熔断或者熔断不起效时,调用方会直接报错返回到页面(没有异常处理的情况下)

开启熔断,接口没有异常,正常返回

接口报错,返回熔断的callback方法

疯狂刷新页面调用接口,接口多次失败,达到熔断阈值,此时看app和demo控制台发现demo根本不会调用app服务,直接返回了callback方法中的值(始终是error),过一会在刷新页面,发现demo又开始调用app接口了,此时是熔断关闭,又开始正常调用了。

熔断原理

熔断主要是为了解决雪崩问题,我们先搞清楚雪崩的原因,导致雪崩的原因有很多种,以流量突增为例。

大量用户请求A,A依赖B,B依赖C。C在处理请求时,首先有个线程池来接收B的调用请求,然后转到处理器中处理请求。

如果C未对连接池设置大小限制,则C会为每个请求创建socket连接,维护在请求队列中,由于C的处理缓慢,最终会到导致C创建大量的socket连接而耗尽C的资料,进而C宕机,而此时B、A又积累了大量的请求,最终导致C、B、A依次宕机。

如果C设置了连接池大小,对超过C最大值的B请求拒绝掉,对于失败的请求B、A、用户都有可能进行重试,B、A中会积累大量用户请求,进而导致B、A中其他业务受影响,无资源可用。

熔断还需要处理程序报错的问题,就像上面演示的那样。

hystrix通过资源隔离的方式,将各个依赖调用相互隔离,保证一个依赖出了问题(被阻塞),不会过多的占用系统资源(也有限流作用),导致其他依赖不能使用,同时使用断路器保存每个依赖的调用情况,统计失败次数,达到预定阈值,打开断路器,后续调用不在执行。通过命令模式将依赖调用封装,调用失败时返回封装对象中的默认返回。

熔断处理流程

资源隔离(上图中的连接池判断、执行)

熔断监控(上图中的统计执行情况)

熔断配置

hystrix提供很多配置项,总体分为三大类,command properties 、Collasper properties、Thread pool propertis。大部分配置都属于Command Properties,共包括五类,

Execution:配置线程池和信号量相关参数

Fallback:配置回调相关参数

Circuit Breaker: 配置断路器相关参数

Metrics:配置汇总统计相关参数

Request Context:配置reqeust上下文相关参数

在熔断流程中,大概控制的环节如下

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值