Hystrix简介及使用

1. Hystrix简介

Hystrix是由Netflix开源的一个延迟和容错库,用 于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。Hystrix主 要通过以下几点实现延迟和容错。

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

2. Hystrix熔断器使用及配置

  • 服务消费者工程中引入Hystrix依赖坐标(也可以添加在父工程中)
<!--熔断器Hystrix--> 
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-hystrix</artifactId> 
</dependency>
  • 服务消费者工程的启动类中添加熔断器开启注解@EnableCircuitBreaker
@SpringBootApplication
@EnableDiscoveryClient
//@EnableHystrix  // 开启Hystrix功能
@EnableCircuitBreaker  // 开启熔断器功能
//@SpringCloudApplication  综合性的注解  @SpringCloudApplication  = @SpringBootApplication + @EnableDiscoveryClient + @EnableCircuitBreaker
public class AutodeliverApplication {

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


    // 使用RestTemplate模板对象进行远程调用
    @Bean
    //Ribbon负载均衡
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
    
}
  • 定义服务降级处理方法,并在业务方法上使用@HystrixCommand的fallbackMethod属性关联到服务降级处理方法
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/autodeliver")
public class AutodeliverController {

    @Autowired
    RestTemplate restTemplate;

    /**
     * 提供者模拟处理超时,调用方法添加Hystrix控制
     *
     * @param userId
     * @return
     */
    // 使用@HystrixCommand注解进行熔断控制,此处没有指明fallbackMethod方法
    @HystrixCommand(
            // 线程池标识,要保持唯一,不唯一的话就共用默认线程池
            threadPoolKey = "findResumeOpenStateTimeout",
            // 线程池细节属性配置
            threadPoolProperties = {
                    // 线程数
                    @HystrixProperty(name = "coreSize", value = "1"),
                    // 等待队列长度
                    @HystrixProperty(name = "maxQueueSize", value = "20")
            },
            // commandProperties熔断的一些细节属性配置
            commandProperties = {
                    // 每一个属性都是一个HystrixProperty
                    //超时时间
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
            }
    )
    @GetMapping("/checkStateTimeout/{userId}")
    public Integer findResumeOpenStateTimeout(@PathVariable Long userId) {
        // 使用ribbon不需要我们自己获取服务实例然后选择一个那么去访问了(自己的负载均衡)
        String url = "http://lagou-service-resume/resume/openstate/" + userId;  // 指定服务名
        Integer forObject = restTemplate.getForObject(url, Integer.class);
        return forObject;
    }


    @GetMapping("/checkStateTimeoutFallback/{userId}")
    @HystrixCommand(
            // 线程池标识,要保持唯一,不唯一的话就共用了
            threadPoolKey = "findResumeOpenStateTimeoutFallback",
            // 线程池细节属性配置
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "2"), // 线程数
                    @HystrixProperty(name = "maxQueueSize", value = "20") // 等待队列长度
            },
            //commandProperties熔断的一些细节属性配置
            commandProperties = {
                    // 每一个属性都是一个HystrixProperty
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000"),
                    // hystrix高级配置,定制工作过程细节
                    // 统计时间窗口定义
                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "8000"),
                    // 统计时间窗口内的最小请求数
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2"),
                    // 统计时间窗口内的错误数量百分比阈值
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
                    // 自我修复时的活动窗口长度
                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "3000")
            },
            fallbackMethod = "myFallBack"  // 回退方法
    )
    public Integer findResumeOpenStateTimeoutFallback(@PathVariable Long userId) {
        // 使用ribbon不需要我们自己获取服务实例然后选择一个那么去访问了(自己的负载均衡)
        String url = "http://lagou-service-resume/resume/openstate/" + userId;  // 指定服务名
        Integer forObject = restTemplate.getForObject(url, Integer.class);
        return forObject;
    }

    /**
     * 定义回退方法,返回预设默认值
     * 注意:该方法形参和返回值与原始方法保持一致
     *
     * @param userId
     * @return
     */
    public Integer myFallBack(Long userId) {
        // 兜底数据
        return -1;
    }
}

参数配置及说明在上面的代码中已经注释了,示例是对每个方法单独配置,需要注意的是降级(兜底)方法必须和被降级方法相同的方法签名(相同参数列表、相同返回值)。如果想要对每个方法采用统一的配置可以在类上使用@DefaultProperties注解统一指定整个类中共用的降级(兜底)方法以及相关配置信息,如下

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DefaultProperties {
    String groupKey() default "";
	//线程池标识
    String threadPoolKey() default "";
	//熔断的一些细节属性配置
    HystrixProperty[] commandProperties() default {};
	//线程池细节属性配置
    HystrixProperty[] threadPoolProperties() default {};

    Class<? extends Throwable>[] ignoreExceptions() default {};

    HystrixException[] raiseHystrixExceptions() default {};
	//默认兜底方法
    String defaultFallback() default "";
}

3. Hystrix舱壁模式(线程池隔离策略)

在这里插入图片描述
如上所示,如果不进行任何设置,所有熔断方法使用一个Hystrix线程池(10个线程),那么这样的话会导致问题,这个问题并不是扇出链路微服务不可用导致的,而是我们的线程机制导致的,如果方法A的请求把 10个线程都用了,方法2请求处理的时候压根都没法去访问B,因为没有线程可用,并不是B服务不可 用。

  • 舱壁模式示意图

在这里插入图片描述
在这里插入图片描述
如上图所示,舱壁模式就如同船中间的隔板,没有中间的隔板,船上所有的食品都会受到影响破坏,有隔板的话,如果一侧出现漏洞,只会影响一部分食品。这种资源隔离的方式就是舱壁模式。
为了避免问题服务请求过多导致正常服务无法访问,Hystrix 不是采用增加线程数,而是单独的为每一 个控制方法创建一个线程池的方式,这种模式叫做“舱壁模式",也是线程隔离的手段。在上面的代码示例中通过threadPoolKey和threadPoolProperties对每个方法配置单独的线程池,使他们互相不受影响。注意:threadPoolKey必须唯一,如果一样就会共享。

4. Hystrix工作流程与高级应用

在这里插入图片描述

  1. 当调用出现问题时,开启一个时间窗(10s)
  2. 在这个时间窗内,统计调用次数是否达到最小请求数?
    如果没有达到,则重置统计信息,回到第1步
    如果达到了,则统计失败的请求数占所有请求数的百分比,是否达到阈值?
    如果达到,则跳闸(不再请求对应服务) ,如果没有达到,则重置统计信息,回到第1步
  3. 如果跳闸,则会开启一个活动窗口(默认5s),每隔5s,Hystrix会让一个请求通过,到达那个问题服务,看是否调用成功,如果成功,重置断路器回到第1步,如果失败,回到第3步

以上参数设置配置如下

 
/**
* 8秒钟内,请求次数达到2个,并且失败率在50%以上,就跳闸 * 跳闸后活动窗口设置为3s
*/
@HystrixCommand( commandProperties = {
	@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "8000"),
	@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "2"),
	@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),
	@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "3000")
} )

我们上述通过注解进行的配置也可以配置在配置文件中

 
# 配置熔断策略: 
hystrix:
 command:
  default:
   circuitBreaker:
    # 强制打开熔断器,如果该属性设置为true,强制断路器进入打开状态,将会拒绝所有的请求。 默认false关闭的 
	forceOpen: false
	# 统计时间窗口
	timeInMilliseconds: 8000
	# 触发熔断错误比例阈值,默认值50% 
	errorThresholdPercentage: 50
    # 熔断后休眠时⻓,默认值5秒 
    sleepWindowInMilliseconds: 3000
    # 熔断触发最小请求次数,默认值是20 
    requestVolumeThreshold: 2
   execution:
    isolation:
     thread:
      # 熔断超时设置,默认为1秒
      timeoutInMilliseconds: 2000

通过以下配置,可以调用http://ip:port/actuator/health 这个接口访问服务健康状态

# springboot中暴露健康检查等断点接口
management:
  endpoints:
    web:
      exposure:
        include: "*"
  # 暴露健康接口的细节
  endpoint:
    health:
      show-details: always

能访问上个接口的前提是在项目用引入下面的依赖

<!-- Actuator可以帮助你监控和管理Spring Boot应用-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值