Hystrix学习

Hystrix学习

概述

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

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

Hystrix能干哪些事?

  1. 服务熔断(break)

    ​ 比如系统达到最大访问量的时候,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示!

  2. 服务降级(fallback)

    ​ 当程序运行异常、超时、服务熔断触发降级、线程池/信号量打满导致服务降级的时候,通过服务器忙,请稍后重试,不让客户端等待并立刻返回一个友好的提示!

  3. 接近实时的监控

  4. 限流(flowlimit)

    ​ 秒杀高并发操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行

服务降级实操及应用场景

触发场景

比如程序运行异常、超时、服务宕机等都要进行服务降级

依赖添加

<dependencies>
    <!--引用工具模块-->
    <dependency>
        <groupId>com.lwp</groupId>
        <artifactId>mz-common</artifactId>
    </dependency>
    <!--服务降级熔断hystrix-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <!--因为在springcloud2020.0.3版本netflix已经被移除,所以需要显示的添加依赖-->
        <version>2.2.6.RELEASE</version>
    </dependency>
    <!--Eureka Client依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

服务提供者定义超时或者报错方法

@Service
public class PaymentService {
    /**
     * 测试超时或者报错的方法是否会进入服务降级
     * @return
     */
    @HystrixCommand(fallbackMethod = "testTimeoutOrErrorHandle", //降级处理方法
       commandProperties = { //降级超时策略,更多策略官网:https://gitee.com/nilera/Hystrix/wikis/Configuration?sort_id=2684424
           @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
       }
    )
    public String testTimeoutOrError(String id){
        int time = 5;
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //int a=10/0; //注释上面线程睡眠方法测试报错降级,同样成功降级
        return "当前线程:"+Thread.currentThread().getName()+"\t"+"成功!"+id;
    }

    /**
     * 服务降级方法
     * @param id
     * @return
     */
    private String testTimeoutOrErrorHandle(String id){
        return "当前线程:"+Thread.currentThread().getName()+"\t"+"降级成功!"+id;
    }

}

启动类添加注解开启降级服务

@SpringBootApplication
@EnableHystrix  //启用Hystrix,旧版本使用@EnableCircuitBreaker注解启用
public class HystrixPaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixPaymentMain8001.class,args);
    }
}

默认全局降级定义

如果每个方法去定义服务降级,容易造成代码膨胀以及业务混乱,这时候我们可以通过全局默认服务降级进行配置,使没有定义降级方法的进入全局降级方法,只有特殊业务处理的才进入自定义的降级方法

实现

@Service
//定义全局默认降级
@DefaultProperties(defaultFallback="defaultGlobalHandle")
public class PaymentService {
    /**
     * 测试超时或者报错的方法是否会进入服务降级
     * @return
     */
    @HystrixCommand(fallbackMethod = "testTimeoutOrErrorHandle", //降级处理方法
       commandProperties = { //降级超时策略,更多策略官网:https://gitee.com/nilera/Hystrix/wikis/Configuration?sort_id=2684424
           @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
       }
    )
    public String testTimeoutOrError(String id){
//        int time = 2;
//        try {
//            TimeUnit.SECONDS.sleep(time);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        int a=10/0; //测试报错降级
        return "当前线程:"+Thread.currentThread().getName()+"\t"+"成功!"+id;
    }

    /**
     * 特定服务降级方法
     * @param id
     * @return
     */
    private String testTimeoutOrErrorHandle(String id){
        return "当前线程:"+Thread.currentThread().getName()+"\t"+"降级成功!"+id;
    }

    @HystrixCommand //该注解一定要加才能交由hystrix管理,触发默认降级方法
    public String testGlobal(){
        int a = 2/0;
        return "呵呵!";
    }

    /**
     * 默认全局降级处理方法
     * @return
     */
    public String defaultGlobalHandle(){
        return "全局降级处理方法----";
    }

}

OpenFeign+Hystrix实现服务降级

yaml配置启用OpenFeign+Hystrix

feign:
# hystrix: cloud2020版本之前使用,之后使用circuitbreaker
  circuitbreaker:
    enabled: true #开启支持

OpenFeign服务接口编写

@Component
//value:服务名称,fallback:服务降级处理类
@FeignClient(value = "HYSTRIX-SERVICE-PAYMENT",fallback = PaymentOpenFeignImpl.class)
public interface PaymentOpenFeign {

    @RequestMapping("/payment/test/{id}")
    public AjaxResult test(@PathVariable("id") String id);
}

OpenFeign降级类定义

@Component
public class PaymentOpenFeignImpl implements PaymentOpenFeign{
    @Override
    public AjaxResult test(String id) {
        return AjaxResult.error("请求的服务器以宕机,请稍后重试!");
    }
}

测试结论

当访问消费端服务时,服务提供者如果正常提供服务,返回服务提供者的信息,如果服务提供者宕机或者异常,返回OpenFeign指定的实现类来处理服务降级

注意:如果OpenFeign开启Hystrix支持失败,为hystrix版本太低,比如我对2.1.6.RELEASE测试开启支持失败,升级到2.2.6.RELEASE便可以使用

降级理解

服务端提供者和消费者都可以进行服务降级,一般服务降级放在客户端

服务熔断实操及应用场景

熔断机制描述

​ 熔断机制是应对雪崩效应的一种微服务链路保护机制,当扇出链路的某个微服务出错不可用或者响应时间太长,会进行服务降级,进而熔断该节点微服务的调用,快速返回错误的响应消息。

​ 在Spring Cloud框架中,熔断机制通过Hystrix实现,Hystrix会监控微服务之间的调用状况,当失败的调用达到一定的阈值,缺省是5秒内调用失败20次,就会启动熔断机制,熔断机制的注解是@HystrixCommand

​ 牛逼点:当检测到该节点微服务调用响应正常后,恢复调用链路

代码实操

service添加方法测试

@Service
public class PaymentService {
   
    //------------------服务熔断------------
    //更多的@HystrixCommand属性设置查看HystrixCommandProperties类
    @HystrixCommand(fallbackMethod = "testRdHandle",commandProperties = {
            //启用断路器
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
            //设置请求次数
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
            //设置时间窗口期
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
            //设置失败率,失败率达到设定的值触发熔断
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
    })
    public String testRd(Integer age){
        if(age>18){
            throw new RuntimeException("年龄太大");
        }
        return "年龄刚刚好!";
    }

    private String testRdHandle(Integer age){
        return "年龄太大,服务降级处理!";
    }
}

控制层添加方法测试

@RestController
@RequestMapping("/payment")
public class PaymentController {

    @Autowired
    private PaymentService paymentService;
   
     /**
     * 熔断测试
     * @param age 年龄阈值
     * @return
     */
    @RequestMapping("/testRd/{age}")
    public AjaxResult testRd(@PathVariable("age") Integer age){
        return AjaxResult.success(paymentService.testRd(age));
    }
}

测试结论

//更多的@HystrixCommand属性设置查看HystrixCommandProperties类
@HystrixCommand(fallbackMethod = "testRdHandle",commandProperties = {
    //启用断路器
    @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
    //设置请求次数
    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
    //设置时间窗口期
    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
    //设置失败率,失败率达到设定的值触发熔断
    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
})

​ 根据以上策略,我们只需要在10秒内,请求10次,错误率达到百分之60就会触发熔断机制,一旦熔断机制触发,断路器开启,这时候我们哪怕发生正确的请求,响应的也是服务降级的处理方法,在一段时间后(默认5秒)断路器处于半开状态,尝试将请求转发,如果得到正确的响应。则将断路器关闭,恢复正常调用!

Hystrix DashBoard监控搭建

依赖添加

<dependencies>
    <!--导入 hystrix 与 hystrix-dashboard 依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.lwp</groupId>
        <artifactId>mz-common</artifactId>
    </dependency>
</dependencies>

配置文件创建

server:
  port: 9001

服务启动

@SpringBootApplication
@EnableHystrixDashboard //开启服务监控
public class HystrixDashboardMain9001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardMain9001.class,args);
    }
}

服务监控

服务启动后访问:http://127.0.0.1:9001/hystrix

被监控的服务暴露端点

主启动类添加Bean

@SpringBootApplication
@EnableHystrix  //启用Hystrix,旧版本使用@EnableCircuitBreaker注解启用
public class HystrixPaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixPaymentMain8001.class,args);
    }

    /**
     * 暴露监控流
     * @return
     */
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet() {
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        return registrationBean;
    }
}

代码参考

hystrix-payment-8001

hystrix-order-90

hystrix-dashboard-9001

posted @ 2021-08-07 19:47  幸运刘  阅读(69)  评论(0)    收藏  举报