Hystrix简介与服务熔断,服务降级,Hystrix监控页面

什么是Hystrix

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式环境中,许多服务依赖关系不可避免地会失败,比如网络延迟导致的服务超时,服务异常等等。Hystrix能保证某一个服务出问题的情况下,不会导致服务整体失败,避免级联故障,提高分布式系统的弹性。

Hystrix实现了断路器的模式,当某个服务发生故障之后,通过断路器的故障监控,向调用方返回一个符合预期的、可处理的备选方案,而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩的发生。

 服务熔断

服务熔断就类似于家庭中的保险丝,当调用分布式系统中某一个服务时,在一定的时间内,这个服务发生的故障次数达到一定的条件,就打开断路器,不在继续调用这个服务,而是直接去调用他的降级服务,这时熔断器的状态为Open。

等过了一段时间后,也就是断路器打开之后休眠时间过后,熔断器进入Half-Open,半开状态,这时尝试对被熔断的服务进行调用,如果依然调用失败,熔断器继续进入Open状态,如果调用成功,熔断器进入Closed状态。

服务降级

服务降级是在系统压力过大的情况下,为了预防某些服务出现负荷过载或者响应慢的情况,在其内部暂时舍弃一些非核心的接口和数据的请求,直接向用户返回一个友好的提示,告知用户服务暂时不可用,虽然提供的是一个有损的服务,但却保证了整个系统的稳定性和可用性。

应用实例

我们先感受一哈服务降级

先看服务降级

服务降级有两种解决方案:

1.从服务提供方进行降级   2.从服务消费方进行降级

先看服务提供方降级

提供方还是用eureka集群那篇文章里用的代码,下面进行一些修改

1.引入hystrix依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>

2.之前服务提供方是从数据库查询数据,现在我们让它在没有查找到数据的时候抛出异常,如果没有服务降级,系统肯定报错,但是引入了Hystrix后,我们让它在抛出异常后,调用他的fallback方法,向用户进行反馈。

    @GetMapping("/dept/{id}")
    @HystrixCommand(fallbackMethod = "queryByIdHystrix"))  //当服务抛出异常后,调用备用方案
    public Dept queryById(@PathVariable("id") int id){
        System.out.println("首选方案执行了111");
        Dept dept = deptService.queryById(id);
        if(dept==null)
            throw  new RuntimeException("用户不存在");
        return dept;
    }

    /**
     * queryById的备用方案
     * fallback方法的声名必须和原方法一致
     */
    public Dept queryByIdHystrix(@PathVariable("id") int id){
        System.out.println("备选方案执行了222");
        Dept dept = new Dept();
        dept.setDeptno(id);
        dept.setDeptname("没有查到");
        return dept;
    }

3.在启动类上添加注解

@EnableCircuitBreaker  

然后启动eureka注册中心,服务提供方和服务消费方

当我们查询数据库中存在的数据时

控制台输出

查询数据库中不存在的数据时

控制台输出:

这是先执行了查询方法,没有找到抛出异常,然后执行了提前写好的fallback方法 

然后是服务消费方降级 

这里的服务消费方还是feign那篇文章中用的代码,下面对其进行修改

feign的本地接口类DeptConsumerService

@FeignClient(value="SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptConsumerServiceFallBack.class)
public interface DeptConsumerService {
    @GetMapping("/dept/{id}")
    public Dept queryById(@PathVariable("id") int id);
    @GetMapping("/dept/all")
    public List<Dept> queryAll();
    @PostMapping("/dept/add")
    public boolean addDept(Dept dept);
}

这个接口本来是要向"SPRINGCLOUD-PROVIDER-DEPT"获取服务,但是由于某些原因,比如服务器宕机,或者系统压力过大这个服务被停掉了,就找到DeptConsumerServiceFallBack这个类,由它来提供一个实现编辑好的服务,告知用户服务不可用。

DeptConsumerServiceFallBack类的编写

这个类要实现FallbackFactory接口,接口中有一个create方法需要实现,我们要返回DeptConsumerService对象

public class DeptConsumerServiceFallBack implements FallbackFactory {
    public DeptConsumerService create(Throwable throwable) {
        return new DeptConsumerService() {
            public Dept queryById(int id) {
                System.out.println("客户端主动降级");
                Dept dept = new Dept();
                dept.setDeptname("没有获取到服务,服务降级");
                return dept;
            }
            public List<Dept> queryAll() {
                return null;
            }
            public boolean addDept(Dept dept) {
                return false;
            }
        };
    }
}

在application.yml文件中开启服务降级

feign:
  hystrix:
    enabled: true

其他的地方不用修改,和以前保持一致即可

启动服务

查询服务中存在的数据

查询服务中没有的数据

经过以上两次查询,控制台输出

当我们关闭服务提供者

再次查询

 控制台输出

 我们可以看到,在服务提供方关闭的情况下,消费方依然可以通过服务降级来给用户进行友好的提示,增强服务的可用性

同时,提供方和消费方同时配置了服务降级,在消费方能正常获取提供方的服务的情况下,调用的是提供方的服务降级,在消费方不能获取提供方的服务时,调用的是消费方的服务降级。

监控页面的配置

新建一个module

导入依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>

在application.yml中修改端口

server:
  port: 9001

创建一个启动类

@SpringBootApplication
@EnableHystrixDashboard
public class DeptDashboard {
    public static void main(String[] args) {
        SpringApplication.run(DeptDashboard.class,args);
    }
}

启动项目,访问   http://localhost:9001/hystrix

就能看到猪猪了(Hystrix --豪猪)

 我们要监控服务提供方,所以要对提供方进行配置

引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>

在application.yml中添加配置

management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream

然后就可以启动项目

服务提供方的端口号为8001,在猪猪页面输入地址就可以进行监控

当消费方向提供方发送请求后,就可以在监控页面看到信息

 服务熔断

我们刚才已经说了什么是服务熔断,就是当服务发生的故障次数达到一定的条件,就打开断路器,不在继续调用这个服务,而是直接去调用他的降级服务,断路器打开,当一段时间过后,断路器进入半开状态,发现服务恢复正常,再把断路器关闭。

下面我们就来感受一哈。

首先需要对服务提供方进行一些配置,主要对Hystrix进行一些配置

@GetMapping("/dept/{id}")
    @HystrixCommand(fallbackMethod = "queryByIdHystrix",commandProperties = {
            @HystrixProperty(name="circuitBreaker.enabled",value = "true"),//熔断器在整个统计时间内是否开启
            @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "10"), // 至少有10个请求才进行熔断错误比率
            // 计算,在一个窗口时间内(默认10秒),只收到收到9个请求,即使这9个请求都失败了,断路器也不会打开
            @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value ="50"),//当出错率超过50%后熔断器启动
            @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "10000")//用来设置当断路器打开之后的休眠
            // 时间,休眠时间结束之后,会将断路器设置为“半开”状态,尝试请求被熔断的服务,如果服务恢复,就关闭熔断器,否咋继续打开
    })
    public Dept queryById(@PathVariable("id") int id){
        System.out.println("首选方案执行了111");
        Dept dept = deptService.queryById(id);
        if(dept==null)
            throw  new RuntimeException("用户不存在");
        return dept;
    }

    /**
     * queryById的备用方案
     * @return
     */
    public Dept queryByIdHystrix(int id){
        System.out.println("备选方案执行了222");
        Dept dept = new Dept();
        dept.setDeptno(id);
        dept.setDeptname("没有查到");
        return dept;
    }

然后启动服务

当我们查询数据库中不存在的数据时

控制台输出

说明先执行了查询方法,然后执行了fallback方法

但是当我们一直提交查询,提交9次,9次都失败,失败率100%,但是断路器依旧是关闭的状态,因为我们设置了circuitBreaker.requestVolumeThreshold,只有在一个窗口时间内,超过10次,才开始计算熔断错误比率

我们这次提交11次,我们看到熔断器已经打开

熔断器打开后,在熔断器休眠时间内,就是我们配置的circuitBreaker.sleepWindowInMilliseconds,无论是查询数据库中存在的数据,还是不存在的数据,查询方法都不会执行,会直接执行fallback方法,查看控制台输出

 当休眠时间结束后,如果我们继续查询数据库中不存在的数据,就会抛出异常,那么熔断器就会继续进入打开状态,如果我们查询数据库中存在的数据,就没有异常,那么熔断器就会关闭

就先写这么多吧 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值