SpringCloud(六):SpringCloud 服务熔断 Hystrix

发布于 2019-08-25 11:36:05

6-1. Hystrix 是什么

在微服务架构中,我们是将一个单体应用拆分成多个服务单元,各个服务单元之 间通过注册中心彼此发现和消费对方提供的服务,每个服务单元都是单独部署, 在各自的服务进程中运行,服务之间通过远程调用实现信息交互,那么当某个服务的响应太慢或者故障,又或者因为网络波动或故障,则会造成调用者延迟或调 用失败,当大量请求到达,则会造成请求的堆积,导致调用者的线程挂起,从而 引发调用者也无法响应,调用者也发生故障。

比如电商中的用户下订单,我们有两个服务,一个下订单服务,一个减库存服务, 当用户下订单时调用下订单服务,然后下订单服务又调用减库存服务,如果减库 存服务响应延迟或者没有响应,则会造成下订单服务的线程挂起等待,如果大量 的用户请求下订单,或导致大量的请求堆积,引起下订单服务也不可用,如果还 有另外一个服务依赖于订单服务,比如用户服务,它需要查询用户订单,那么用 户服务查询订单也会引起大量的延迟和请求堆积,导致用户服务也不可用。 所以在微服务架构中,很容易造成服务故障的蔓延,引发整个微服务系统瘫痪不 可用。为了解决此问题,微服务架构中引入了一种叫熔断器的服务保护机制。

熔断器也有叫断路器,他们表示同一个意思,最早来源于微服务之父 Martin Fowler的论文CircuitBreaker一文。“熔断器”本身是一种开关装置,用于在 电路上保护线路过载,当线路中有电器发生短路时,能够及时切断故障电路,防 止发生过载、发热甚至起火等严重后果

微服务架构中的熔断器,就是当被调用方没有响应,调用方直接返回一个错误响 应即可,而不是长时间的等待,这样避免调用时因为等待而线程一直得不到释放, 避免故障在分布式系统间蔓延

Spring Cloud Hystrix实现了熔断器、线程隔离等一系列服务保护功能。该功能 也是基于 Netflix 的开源框架 Hystrix 实现的,该框架的目标在于通过控制那些 访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能 力。Hystrix 具备服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并 以及服务监控等强大功能

6-2. Hystrix 快速入门

在 SpringCloud 中使用熔断器 Hystrix 是非常简单和方便的,只需要简单两步 即可:

1、添加依赖

在服务消费者中添加依赖

<!--Spring Cloud熔断器起步依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.4.RELEASE</version>
        </dependency>

2、在入口类中使用@EnableCircuitBreaker注解开启断路器功能,也可以使用 一个名为@SpringCloudApplication的注解代替主类上的三个注解

3、在调用远程服务的方法上添加注解: @HystrixCommand(fallbackMethod="error")

demo:

image.png

image.png

@RequestMapping("/web/hystrix")
    @HystrixCommand(fallbackMethod = "error")   //发生错误后执行error方法
    public String hystrix(){
        return restTemplate.getForEntity("http://01-springcloud-service-provider/service/hello",String.class).getBody();
    }

    // 发生错误后执行的方法
    public String error(){
        return "error";
    }

启动服务提供者1,服务提供者2,服务消费者,以及Eureka注册中心,策略改为轮询策略,然后访问http://localhost:8081/web/hystrix

image.png

image.png

轮询策略,断掉服务提供者2,使其发生异常,然后再访问http://localhost:8081/web/hystrix
观察页面显示,服务2访问不通,执行了error方法

image.png

image.png

6-3. 服务消费者 Hystrix 测试

hystrix 默认超时时间是 1000 毫秒,如果你后端的响应超过此时间,就会触发 断路器
修改hystrix的默认超时时间

@RequestMapping("/web/hystrix")
    @HystrixCommand(fallbackMethod = "error",commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1500")})   //发生错误后执行error方法
    public String hystrix(){
        return restTemplate.getForEntity("http://01-springcloud-service-provider/service/hello",String.class).getBody();
    }

6-4. Hystrix 的服务降级

有了服务的熔断,随之就会有服务的降级,所谓服务降级,就是当某个服务熔断 之后,服务端提供的服务将不再被调用,此时由客户端自己准备一个本地的 fallback回调,返回一个默认值来代表服务端的返回; 这种做法,虽然不能得到正确的返回结果,但至少保证了服务的可用,比直接抛 出错误或服务不可用要好很多,当然这需要根据具体的业务场景来选择;

6-5. Hystrix 的异常处理

我们在调用服务提供者时,我们自己也有可能会抛异常,默认情况下方法抛了异
常会自动进行服务降级,交给服务降级中的方法去处理;
当我们自己发生异常后,只需要在服务降级方法中添加一个 Throwable 类型的
参数就能够获取到抛出的异常的类型,如下

 public String error(Throwable throwable){
        System.out.println(throwable.getMessage());
        return "error";
    }

image.png

此时我们可以在控制台看到异常的类型;
如果远程服务有一个异常抛出后我们不希望进入到服务降级方法中去处理,而是
直接将异常抛给用户,那么我们可以在@HystrixCommand注解中添加忽略异
常,如下:

@HystrixCommand(fallbackMethod="error", ignoreExceptions = Exception.class)

如:

 @RequestMapping("/web/hystrix")
    @HystrixCommand(fallbackMethod = "error",ignoreExceptions = Exception.class,commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1500")})   //发生错误后执行error方法
    public String hystrix(){
        int a = 10/0;     // 模拟异常  除数不能为0,会抛出异常
        return restTemplate.getForEntity("http://01-springcloud-service-provider/service/hello",String.class).getBody();
    }

自定义Hystrix请求的服务异常熔断处理

我们也可以自定义类继承自 HystrixCommand 来实现自定义的Hystrix 请求,
在 getFallback 方法中调用 getExecutionException 方法来获取服务抛出的异

com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(""))

demo:

新建一个类MyHystrixCommand

image.png

/**
 * 自定义Hystrix请求
 */
public class MyHystrixCommand extends HystrixCommand<String> {


    private RestTemplate restTemplate;

    public MyHystrixCommand(Setter setter,RestTemplate restTemplate){
        super(setter);
        this.restTemplate = restTemplate;

    }
    @Override
    protected String run() throws Exception {
        return restTemplate.getForEntity("http://01-springcloud-service-provider/service/hello",String.class).getBody();
    }


    @Override   // 当服务降级/熔断以后会执行此方法
    protected String getFallback() {
        // 实现服务降级熔断逻辑
        return "error";
    }
}

image.png

 @RequestMapping("/web/hystrix2")
    @HystrixCommand(fallbackMethod = "error",ignoreExceptions = Exception.class,commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1500")})   //发生错误后执行error方法
    public String hystrix2(){
        MyHystrixCommand command = new MyHystrixCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")),restTemplate);

        String str = command.execute();
        return str;
    }

同步调用/异步调用

@RequestMapping("/web/hystrix2")
    @HystrixCommand(fallbackMethod = "error",ignoreExceptions = Exception.class,commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1500")})   //发生错误后执行error方法
    public String hystrix2() throws ExecutionException, InterruptedException {
        MyHystrixCommand command = new MyHystrixCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")),restTemplate);
        // 同步调用 (该方法执行后,会等待远程的返回结果,拿到了返回结果,该方法才返回,程序继续向下集成)
       // String str = command.execute();
        // 异步调用 (该方法执行后,不会立刻返回远程的结果,将来会有结果)
       Future<String> future =  command.queue();
        // 业务逻辑
       // 阻塞的方法,直到拿到结果 程序将往下执行
       String str = future.get();    // 一直等,等到拿到返回结果
        // 业务逻辑
        return str;
    }

SpringCloud-Hystrix的自定义请求异常熔断处理

## 6-6. Hystrix 仪表盘监控

Hystrix 仪表盘(Hystrix Dashboard),就像汽车的仪表盘实时显示汽车的各
项数据一样,Hystrix 仪表盘主要用来监控 Hystrix 的实时运行状态,通过它我们可以看到Hystrix的各项指标信息,从而快速发现系统中存在的问题进而解决
它。

要使用Hystrix仪表盘功能,我们首先需要有一个Hystrix Dashboard,这个功
能我们可以在原来的消费者应用上添加,让原来的消费者应用具备Hystrix仪表
盘功能,但一般地,微服务架构思想是推崇服务的拆分,Hystrix Dashboard也
是一个服务,所以通常会单独创建一个新的工程专门用做 Hystrix Dashboard
服务;

搭建一个Hystrix Dashboard服务的步骤:

第一步:创建一个普通的Spring Boot工程
比如创建一个名为springcloud-hystrix-dashboard的Spring Boot工程,建
立好基本的结构和配置;

第二步:添加相关依赖
在创建好的Spring Boot项目的 pom.xml文件中添加相关依赖,如下

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

第三步:入口类上添加注解
添加好依赖之后,在入口类上添加@EnableHystrixDashboard注解开启仪表盘
功能,如下:

@SpringBootApplication
@EnableHystrixDashboard
public class Application {

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

}

第四步:属性配置
最后,我们可以根据个人习惯配置一下application.properties文件,如下:
server.port=3721

至此,我们的Hystrix监控环境就搭建好了;

启动程序 访问http://localhost:3721/hystrix

image.png

Hystrix 仪表盘工程已经创建好了,现在我们需要有一个服务,让这个服务提供
一个路径为/actuator/hystrix.stream 接口,然后就可以使用 Hystrix 仪表盘来
对该服务进行监控了;

我们改造消费者服务,让其能提供/actuator/hystrix.stream接口,步骤如下:
1、消费者项目需要有hystrix的依赖

  <!--Spring Cloud熔断器起步依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.4.RELEASE</version>
        </dependency>

2、需要有一个spring boot的服务监控依赖:

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

3、配置文件需要配置spring boot监控端点的访问权限

management.endpoints.web.exposure.include=* 

这个是用来暴露 endpoints 的,由于 endpoints 中会包含很多敏感信息,除
了 health 和 info 两个支持直接访问外,其他的默认不能直接访问,所以我们
让它都能访问,或者指定:

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

4、访问入口 http://localhost:8081/actuator/hystrix.stream

注意:这里有一个细节需要注意,要访问/hystrix.stream接口,首先得访问
consumer工程中的任意一个其他接口(可以触发熔断器的接口,这里我就访问http://localhost:8081//web/hystrix),否则直接访问/hystrix.stream接口时
会输出出一连串的ping: ping: …,先访问consumer中的任意一个其他接口,
然后再访问/hystrix.stream接口即可

6-7. Hystrix 仪表盘监控数据解读

image.png

QQ图片20190826090840.png

0 条评论

发布
问题