熔断器Hystrix

微服务中服务之间的相互依赖性错综复杂,一个网络请求通常需要调用多个服务实例才能完成。如果一个服务不可用,如网络延迟或故障,会影响依赖于这个服务的其它服务,最后导致整个系统处于瘫痪的状态。为解决这种雪崩效应,引进熔断组件Hystrix,当出现故障后会自动剔除服务实列。Hystrix除了一些基本的熔断器,还能实现服务降级、服务限流的功能,并提供了界面展示健康状态的功能。本章讲诉如何使用RestTemplate和Feign消费服务是使用Hystrix,并介绍Hystrix的工作原理。

Hystrix的设计原则

  • 防止单个服务的故障耗尽整个服务的Servlet容器(如Tomcat)的线程池资源。
  • 快速失败机制,如果某个服务出现了故障,则调用该服务的请求快速失败,而不是线程等待。
  • 提供回退方案,在请求发生故障时,提供设定好的回退方案。
  • 使用熔断器机制,防止故障扩散到其他的服务。
  • 提供熔断器的监控组件Hystrix Dashboard,可以实时监控熔断器的状态。

Hystrix的工作机制

当服务的某个API接口的失败次数在一定时间内小于设定的阈值时,熔断器处于关闭状态,该API接口正常提供服务。当该API接口处理请求的失败次数大于设定的阈值时,Hystrix判定该API接口出现了故障,打开熔断器,这时该API接口会执行快速失败的逻辑,不执行业务逻辑,请求的线程不会处于阻塞状态。处于打开状态的熔断器在一定时间后会处于半打开状态,并将一定数量的请求执行正常逻辑,剩余的请求会执行快速失败。若执行正常逻辑的请求失败了,则熔断器继续打开,若成功了,则熔断器关闭。这样熔断器就具有了自我修复的功能。

在RestTemplate上使用熔断器

本章案例在前面章节的案例基础之上进行改造。在讲述ribbon章节时,eureka-ribbon-client工程中我们使用RestTemplate调用了eureka-client的“/hi”接口,并用Ribbon做了负载均衡,现在在此基础上加Hystrix熔断器的功能。

  • 添加Hystrix的起步依赖
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
  • 在启动类上添加@EnableHystrix注解开启Hystrix的熔断器功能。
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
@EnableHystrixDashboard
public class EurekaRibbonClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaRibbonClientApplication.class, args);
    }
}
  • 修该RibbonService的代码,在方法中加上@HystrixCommand注解。有了@HystrixCommand方法就用Hystrix熔断器的功能,其中,fallbackMethod为处理回退逻辑的方法,在本例中,直接返回了一个字符串。在熔断器打开的状态下,会执行回退逻辑。回退逻辑最好是返回一些静态的字符串,不需要处理复杂的逻辑,也不需要远程调用其它的服务,这样能执行快速失败,释放线程资源。如果在回退逻辑中一定要调用远程服务,最好在远程调度其它的服务时,也加上熔断器。
public class RibbonServiceHystrix {
    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "hiError")
    public String hiFromClient() {
        return restTemplate.getForObject("http://eureka-client/hi?name=dzy", String.class);
    }
    public String hiError(){
        return "error";
    }
}
  • 启动eureka-server和eureka-ribbon-client。此时没有启动eureka-client,所以eureka-ribbon-client肯定是访问不通eureka-client接口的。此时访问http://localhost:8765/hi,浏览器会显示回退逻辑返回的错误字符串。做到了快速失败,线程不在阻塞。

在Feign上使用熔断器

  • 之前介绍Feign提到本身已经集成了熔断器的功能,Feign的起步依赖已经引入了Hystrix的依赖,所以不需要在pom文件中添加Hystrix的依赖。只需要在配置文件中开启Hystrix功能即可。
feign:
  hystrix:
    enabled: true
  • 在声明式接口中的@FeignClient注解上添加fallback属性来配置快速失败的处理类。该处理类作为Feign熔断器的逻辑处理类,必须实现被@FeignClient修饰的接口,最后需要以Spring Bean的形式注入IoC容器中。
@FeignClient(value = "eureka-client", configuration = FeignClientConfig.class,fallback = HiFailBack.class)
public interface HiFeignClient {
    @GetMapping("/hi")
    String hi(@RequestParam(value = "name") String name);
}
@Component
public class HiFailBack implements HiFeignClient {

    @Override
    public String hi(String name) {
        return "hystrix error";
    }
}
  • 启动eureka-server,eureka-feign-client,此时没有启动eureka-client,所以eureka-feign-client接口调用eureka-client的接口是肯定连接不通的。在浏览器访问eureka-feign-client接口,浏览器会出现配置的错误字符串,说明实现了快速失败。

使用Hystrix Dashboard监控熔断器的状态

Hystrix Dashboard 是监控Hystrix的熔断状况的一个组件,提供了数据监控和友好的图形化展示界面。

在RestTemplate中使用Hystrix Dashboard

在eureka-ribbon-client的基础上改造。

  • 在pom文件中加上Actuator的起步依赖,Hystrix Dashboard的起步依赖。
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
  • 在启动类上加上@EnableHystrixDashboard开启Hystrix Dashboard的功能。
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
@EnableHystrixDashboard
public class EurekaRibbonClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaRibbonClientApplication.class, args);
    }
}
  • 依此启动eureka-server,eureka-client和eureka-ribbon-client(我的端口为8765),确定两个eureka client已经注册到了eureka server中。
    在浏览器访问http://localhost:8765/hystrix,会出现Hystrix Dashboard的界面。
    image.png

    在界面中依此填写http://localhost:8765/hystrix.stream,200,forezp(任意填写),点击“monitor”,进入界面
    image.png

    监控图中用圆点来表示服务的健康状态,健康度从100%-0%分别会用绿色、黄色、橙色、红色来表示。 另外,这个圆点也会随着流量的增多而变大。 监控图中会用曲线(圆点旁边)来表示服务的流量情况,通过这个曲线可以观察单个接口的流量变化/趋势。对应的指标含义如下
    image.png

在feign中使用Hystrix Dashboard

  • 添加Actuator,Hystrix,Hystrix Dashboard的起步依赖。这里需要注意,既然Feign自带Hystrix,那为什么还需要引入spring-cloud-starter-hystrix?这是因为Feign自带的是Hystrix的依赖不是Hystrix起步依赖。
 <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>
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • 在启动类上加上@EnableHystrixDashboard开启Hystrix Dashboard的功能。
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrixDashboard
@EnableHystrix
public class EurekaFeignClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaFeignClientApplication.class, args);
    }
}

只需要上述两步就可以在Feign中开启Hystrix Dashboard的功能。

使用Turbine聚合监控

在使用Hystrix Dashboard组件监控服务的熔断状况时,每个服务都有一个Hystrix Dashboard主页,当服务数量很多时,监控非常不方便。为了同时监控多个服务的熔断器的状况,Netflix开源了Hystrix另一个组件Turbine。Turbine用于聚合多个Hystrix Dashboard,将多个Hystrix Dashboard组件的数据放在一个页面上展示,进行集中监控。

  • 新建一个Module工程,取名为turbine-server,在pom中添加turbine,actuator,test的起步依赖。
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
</dependency>

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
 </dependency>
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
 </dependency>
  • 在配置文件application加上相关的配置。
server:
  port: 8770
spring:
  application:
    name: turbine-server
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
management:
  security:
    enabled: false
turbine:
  app-config: eureka-ribbon-client,eureka-feign-client
  cluster-name-expression: new String("default")
  aggregator:
    clusterConfig: default

其中turbine.app-config配置了需要监控的服务名,turbine.cluster-name-expression默认为服务器的集群,此时用默认的即可。turbine.aggregator.clusterConfig可以不写,因为默认就是default。

  • 启动类上添加@EnableTurbine注解,启动Turbine功能
@SpringBootApplication
@EnableEurekaClient
@EnableTurbine
public class TurbineServerApplication {

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

}

  • 启动eureka-server,eureka-ribbon-client,eureka-feign-client,turbine-server
    在浏览器访问http://localhost:8765/hystrix,在这个界面为eureka-ribbon-client的
    Hystrix Dashboard界面(用其它服务的Hystrix Dashboard也可,只要监控流为turbine服务器地址就行,但在项目中只会启用一个服务的Hystrix Dashboard),在界面中依此输入监控流的Url地址http://localhost:8770/turbine.stream,监控时间间隔为2000毫秒和title,点击“monitor”,可以看到如下界面。
    image.png

    可以看到这个界面同时聚合了eureka-ribbon-client和eureka-feign-client的Hystrix Dashboard。

总结

在这一章学习了熔断器Hystrix,其中包括什么是Hystrix,Hystrix的工作原理,TestTemplate、Feign结合Hystrix的使用。最后介绍使用图形化监控组件Hystrix Dashboard,以及监控聚合组件Turbine。在下一章中介绍路由网关Zuul。

PS:项目github地址:https://github.com/dzydzydzy/spring-cloud-example.git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容