SpringCloud之Hystrix(断路器)

分布式系统面临的问题
#### 扇出

多个微服务互相调用的时候,如果A调用B、C,而B、C又继续调用其他微服务,这就是扇出(像一把扇子一样慢慢打开

#### 服务雪崩
- 删除过程中,如果某一个环节的服务出现故障或连接超时,就会导致前面的服务占用越来越多的资源,进而引起系统崩溃,就是“雪崩效应”。

- 对于高流量的应用来说,单一的后端依赖会导致服务器所有的资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要==对故障和延迟进行隔离和管理==,以便单个依赖关系的失败,不能取消整个应用程序或系统

Hystrix 断路器

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

"断路器"本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间,不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩

文档:https://github.com/Netflix/Hystrix/wiki/How-To-Use

服务熔断
熔断机制是应对雪崩效应的一种微服务链路保护机制;
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回"错误"的响应信息;当检测到该节点微服务调用正常后恢复调用链路;

##### 熔断案例
1. 构建一个新的provider module(如复制8001module)
2. pom.xml加入hystrix依赖(一定要配合Eureka)

新建microservicecloud-provider-dept-hystrix-8001

// 参考 microservicecloud-provider-dept-8001

// pom.xml
<!-- hystrix -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

application.xml中配置端口和Eureka信息(必配)和其他框架的配置信息(可选,如mybatis)

// application.yml
eureka:
  client: # 客户端注册进eureka服务列表内
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
  instance:
    instance-id: microservicecloud-dept8001-hystrix # 自定义hystrix相关的服务名称信息
    prefer-ip-address: true  # 访问路径可以显示IP地址

controller类中,在需要配置Fallback的方法上加入@HystrixCommand(fallbackMethod = "XXX")注解,XXX为FallBack方法名本例中作为测试所以抛出了异常

@RestController
public class DeptController {

    @Autowired
    private DeptService deptService;

    @Autowired
    private DiscoveryClient client;

    @RequestMapping(value="/dept/get/{id}",method=RequestMethod.GET)
    // 一旦调用服务方法失败并抛出错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法
    @HystrixCommand(fallbackMethod="processHystrix_Get")  
    public Dept get(@PathVariable("id") Long id) {
        Dept dept = this.deptService.get(id);
        if(null == dept) {
            throw new RuntimeException("该ID:"+id+"没有对应的信息");
        }
        return dept;
    }

    public Dept processHystrix_Get(@PathVariable("id") Long id) {
        return new Dept().setDeptno(id).setDname("该ID:"+id+"没有对应的信息,null -- @HystrixCommand")
                .setDb_source("no this database in MySQL");
    }
}

// 修改主启动类DeptProvider8001_Hystrix_App并添加新注解@EnableCircuitBreaker

@SpringBootApplication
@EnableEurekaClient // 本服务启动后,自动注册进eureka服务中
@EnableDiscoveryClient // 服务发现
@EnableCircuitBreaker // 对Hystrix熔断机制的支持
public class DeptProvider8001_Hystrix_App {

    public static void main(String[] args) {
        SpringApplication.run(DeptProvider8001_Hystrix_App.class, args);
    }
}

// 测试访问:// http://localhost:8082/consumer/dept/get/112


服务降级
服务降级:整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来;
服务降级处理是在客户端实现完成的,与服务端没有关系;

当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值;

##### 为什么要解耦

如果按照上面的熔断案例来做的话,Controller下的每个方法,都要给其编写一个FallBack方法,当方法慢慢变多,就会造成代码膨胀,一个是增加编写的工作量,另外一个也会增大维护的难度,代码的耦合度也会高,是十分不合理的,所以要将其解耦

##### 解耦思路

因为服务端的是通过实现接口访问服务端的,如果在父接口上实现了FallBack方法,通过这样一种方式去维护起来就能实现解耦,也顺便完成了降级的机制

##### 解耦&降级案例

1. 在api模块中新建实现了FallbackFactory<T>接口的类,其中泛型T就是我们需要维护其FallBack的接口方法,并实现其create方法,在create方法中返回实现了T的对象,使用匿名内部类实现T。==注意:这个类一定要加@Component注解!!这个类一定要加@Component注解!!这个类一定要加@Component注解!!==

// 修改microservicecloud-api工程
// 根据已有的DeptClientService接口,新建一个实现了FallbackFactory接口的类DeptClientServiceFallbackFactory

@Component  // 不要忘记添加
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {

    @Override
    public DeptClientService create(Throwable arg0) {

        return new DeptClientService() {

            @Override
            public Dept get(long id) {
                return new Dept().setDeptno(id).setDname("该ID:"+id+"没有对应的信息,Consumer客户端提供的降级信息,此刻服务Provider已经关闭")
                        .setDb_source("no this database in MySQL");
            }

            @Override
            public List<Dept> list() {

                return null;
            }

            @Override
            public boolean add(Dept dept) {

                return false;
            }
        };
    }
}

2. 修改步骤1中传入的泛型T接口,添加@FeignClient(fallbackFactory = T.class)注解
// 修改microservicecloud-api工程, DeptClientService接口

// 在注解@FeignClient中添加 fallbackFactory 属性值

@FeignClient(value="MICROSERVICECLOUD-DEPT",
            fallbackFactory=DeptClientServiceFallbackFactory.class)
public interface DeptClientService {

    @RequestMapping(value="/dept/get/{id}", method= RequestMethod.GET)
    public Dept get(@PathVariable("id") long id);

    @RequestMapping(value="/dept/list", method= RequestMethod.GET)
    public List<Dept> list();

    @RequestMapping(value="/dept/add", method= RequestMethod.POST)
    public boolean add(Dept dept);
}

// mvn clean,// mvn install

3. 修改consumer feign模块的application.xml文件,开启hystrix(注:在IDEA中可能没有代码提示,开启的true也没有正常高亮,但好像不需要做额外操作也不影响结果)

// 修改microservicecloud-consumer-dept-feign 工程

// application.yml

feign:
  hystrix:
    enabled: true
// 测试访问:// http://localhost:8082/consumer/dept/get/1

// 然后手动关闭工程:microservicecloud-provider-dept-8001


HystrixDashboard服务监控

介绍:SpringCloud对Hystrix Dashboard进行了整合,可以对通过Hystrix发起的请求进行准实时统计,并以报表和图形的形式展示给用户(包括每秒执行多少次请求成功和失败等)

##### 配置案例

新建工程microservicecloud-consumer-hystrix-dashboard

1. 新建HystrixDashboard模块,pom.xml文件加入HystrixDashboard依赖,其他依赖包括Feign,Ribbon,Eureka(可参考80模块的依赖)

// pom.xml
<!-- hystrix和hystrix-dashboard 相关 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>

2. application.yml文件中配置端口(如9001)

// application.yml
server:
  port: 9001

3. provider类中确认要加入actuator依赖(此为监控依赖)

// 所有Provider微服务提供类(8001/8002/8003)都需要提供监控依赖配置

// (8001/8002/8003)pom.xml

<!-- actuator 监控信息完善 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

4. 编写主启动类,上标@EnableHystrixDashboard标注

@SpringBootApplication
@EnableHystrixDashboard
public class DeptConsumer_DashBoard_App {

    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_DashBoard_App.class, args);
    }
}

5. 启动服务进行测试,访问地址:http://localhost:9001/hystrix,(根据配置端口号),==看到刺猬表示已经配置好了==


##### 如何监控

- 在dashboard界面中,填入需要监控的服务地址和端口号加上\hystrix.stream和监测间隔即可进入监控。(如http://localhost:8001/hystrix.stream

// 启动相关工程:// microservicecloud-consumer-hystrix-dashboard   // 访问: http://localhost:9001/hystrix
// 3个Eureka集群:// microservicecloud-provider-dept-hystrix-8001
// 访问: http://localhost:8001/dept/get/1,// 访问: http://localhost:8001/hystrix.stream

##### 监控分析
- 七色:进入监控界面后会有其中颜色的数字,其含义可以对应右上角相同颜色的单词表示的状态,其值代表该状态下触发的次数
- 一圈:圈的大小代表该服务的流量,圈越大流量越大
- 一线:代表监控间隔中,服务被访问的频率的折线图
- 通过观察这些就可以在大量的实例中找出故障实例和高压实例进行修复和维护

Dashboard监控说明图:



猜你喜欢

转载自blog.csdn.net/qq_35508033/article/details/80777448