SpringCloud--Hystrix熔断器 (六)

一、Hystrix简介

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


Hystrix如何解决依赖隔离

1、包裹请求:使用HystrixCommand包裹对依赖的调用逻辑,每个命令在独立的线程中执行,使用了设计模式中的“命令模式”;
2、跳闸机制:当某服务的错误率超过一定阈值时,Hystrix可以自动或者手动跳闸,停止请求该服务一段时间;
3、资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程已满,则发向该依赖的请求就会被立即拒绝,而不是排队等候,从而加速失败判定;
4、监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等;
5、回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑,回退逻辑由开发人员自行提供,如返回一个缺省值;
6、自我修复:断路器打开一段时间后,会自动进入“半开”状态,此时断路器可允许一个请求访问依赖的服务,若请求成功,则断路器关闭,否则断路器转为“打开”状态;

形成过程:

1)服务提供者不可用

a)硬件故障:硬件损坏造成的服务器主机宕机, 网络硬件故障造成的服务提供者的不可访问
b)程序Bug:
c) 缓存击穿:缓存击穿一般发生在缓存应用重启, 所有缓存被清空时,以及短时间内大量缓存失效时. 大量的缓存不命中, 使请求直击后端,造成服务提供者超负荷运行,引起服务不可用
d)用户大量请求:在秒杀和大促开始前,如果准备不充分,用户发起大量请求也会造成服务提供者的不可用

2)重试加大流量

a)用户重试:在服务提供者不可用后, 用户由于忍受不了界面上长时间的等待,而不断刷新页面甚至提交表单
b)代码逻辑重试: 服务调用端的会存在大量服务异常后的重试逻辑

3)服务调用者不可用

a)同步等待造成的资源耗尽:当服务调用者使用同步调用 时, 会产生大量的等待线程占用系统资源. 一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态, 于是服务雪崩效应产生了。

  为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。
Hystrix是一个用于分布式系统的延迟和容错的开源库。在分布式系统里,许多依赖不可避免的调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整个服务失败,避免级联故障,以提高分布式系统的弹性。


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

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

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

二、Maven依赖



    org.springframework.cloud
    spring-cloud-starter-netflix-hystrix

三、 主启动类添加注解EnableCircuitBreaker

@SpringBootApplication
@EnableCircuitBreaker //对Hystrix熔断机制的支持
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

四、熔断测试

@RequestMapping(value = "/user/get/{id}", method = RequestMethod.GET)
// 如果当前调用的get()方法出现了错误,则执行fallback
@HystrixCommand(fallbackMethod="getFallback")
public Object get(@PathVariable("id") long id) {
    String vo=null;    // 接收数据库的查询结果
    if (vo == null) {    // 数据不存在,假设让它抛出个错误
        throw new RuntimeException("部门信息不存在!") ;
    }
    return vo ;
}

/**
 * 此时方法的参数 与get()一致
 * @param id
 * @return
 */
public Object getFallback(@PathVariable("id") long id) {
    User vo = new User() ;
    vo.setId(1);
    vo.setUsername("【ERROR】User-Service-Hystrix");    // 错误的提示
    return vo ;
}

现在的处理情况是:服务器出现了错误(但并不表示提供方关闭),那么此时会调用指定方法的 fallback 处理。
什么情况下会触发fallback方法?

名字 描述 触发fallback
EMIT 值传递NO
SUCCESS 执行完成,没有错误 NO
FAILURE 执行抛出异常 YES
TIMEOUT 执行开始,但没有在允许的时间内完成 YES
BAD_REQUEST 执行抛出HystrixBadRequestException NO
SHORT_CIRCUITED 断路器打开,不尝试执行 YES
THREAD_POOL_REJECTED 线程池拒绝,不尝试执行 YES
SEMAPHORE_REJECTED 信号量拒绝,不尝试执行 YES

fallback方法在什么情况下会抛出异常

名字 描述 抛异常
FALLBACK_EMIT Fallback值传递 NO
FALLBACK_SUCCESS Fallback执行完成,没有错误 NO
FALLBACK_FAILURE Fallback执行抛出出错 YES
FALLBACK_REJECTED Fallback信号量拒绝,不尝试执行 YES
FALLBACK_MISSING 没有Fallback实例 YES

五、基于Feign使用Hystrix

通常情况下的Hystrix是通过注解@HystrixCommand的fallbackMethod属性实现回调的,而在Feign中,由于Feign是用接口实现的声明式Rest,所以Hystrix的通用方法在这里就不适用于Feign了,实际上在Feign与SpringCloud的依赖库中已经默认的将Hystrix加入其中了,如图:


基于Feign使用Hystrix
  1. Maven依赖

    org.springframework.cloud
    spring-cloud-starter-feign

  1. application.properties配置
server.port=8762
spring.application.name=user-service
#默认feign的hystrix为关闭状态
feign.hystrix.enabled=true
# 服务注册
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
  1. 启动类
    启动类添加@EnableFeignClients,控制层通过注入feign的接口去完成声明式调用:
@SpringBootApplication
@EnableFeignClients
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
}

  1. 接口类
// 接口类上加入的注解中添加属性fallback,指定回调类
@FeignClient(name = "USER-SERVICE",fallback = FeignClientFallback.class)
public interface UserFeign {
    @RequestMapping("/getUser")
    public String getUser();

}
  1. 回调类
/**
 * @Description: 回调实现类
 */ 
@Component
class FeignClientFallback implements UserFeign {

    @Override
    public String getUser() {
        System.out.println("熔断,默认回调函数");
        return "{\"username\":\"admin\",\"age\":\"-1\"}";
    }
}

6、测试

   @Autowired
    private UserFeign userFeign;
    @Test
    public void getUser() {
        String str = userFeign .getUser();
        log.info("{}", str);
    }

测试方法,服务方法中,产生异常将会调用熔断方法。

你可能感兴趣的:(SpringCloud--Hystrix熔断器 (六))