一、在分布式系统中,服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务会出现故障,导致依赖于它们的其他服务出现远程调度的线程阻塞 Hystrix是Netflix 公司开源的一个项目,它提供了熔断器功能,能够阻止分布式系统中出现联动故障 Hystrix 是通过隔离服务的访问点阻止联动故障的,并提供了故障的解决方案,从而提高了整个分布式系统的弹性

  二、Hystrix的产生:

  在复杂的分布式系统中,可能有几十个服务相互依赖,这些服务由于某些原因,例如机房的不可靠性、网络服务商的不可靠性,导致某个服务不可用。如果系统不隔离该不可用的服务,可能会导致整个系统不可用。

  对于依赖 30 个服务的应用程序,每个服务的正常运行时间为 99.99% ,对于单个服务来说, 99.99% 的可用是非常完美的。有99.99^30 = 99.7% 的可正常运行时间和 0.3% 的不可用时间,那么 10 亿次请求中有 3000000次失败,实际的情况可能比这更糟糕。

  如果不设计整个系统的韧性,即使所有依赖关系表现良好,单个服务只有 0.01% 的不可用,由于整个系统的服务相互依赖,最终对整个系统的影响是非常大的。

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  在上图中一个用户需要请求A、H、I、P。如果中间I服务网络延迟或者发生故障,即A、H、P不可用。在高并发的情况下,单个服务的延迟会导致整个请求都处于延迟状态,可能在几秒钟就使整个服务处于线程负载饱和的状态。

  某个服务的单个点的请求故障会导致用户的请求处于阻塞状态,最终的结果就是整个服务的线程资源消耗殆尽。由于服务的依赖性,会导致依赖于该故障服务的其他服务也处于线程阻塞状态,最终导致这些服务的线程资源消耗殆尽 直到不可用,从而导致整个问服务系统都不可用,即雪崩效应。

  为了防止雪崩效应,因而产生了熔断器模型。 Hystrix 是在业界表现非常好的 个熔断器模型实现的开源组件,它是 Spring Cloud 组件不可缺少的一部分。

  三、Hystrix的设计原则:

  1)防止单个服务的故障耗尽整个服务的 Servlet 容器(例如 Tomcat )的线程资源。

  2)快速失败机制,如果某个服务出现了故障,则调用该服务的请求快速失败,而不是线程等待。

  3)提供回退( fallback )方案,在请求发生故障时,提供设定好的回退方案。

  4)使用熔断机制,防止故障扩散到其他服务。

  5)提供熔断器的监控组件 Hystrix Dashboard ,可以实时监控熔断器的状态。

  四、Hystrix的工作机制:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

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

  五、服务中对Hystrix的基本使用

  1)Ribbon中使用Hystrix熔断器(我们基于前面的Spring-Cloud之Ribbon负载均衡-3代码进行改造)。

  a、加入依赖

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

  b、加入注解(@EnableHystrix)开启熔断器功能

package com.cetc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix; @SpringBootApplication
@EnableEurekaClient
@EnableHystrix
public class HystrixRibbonApplication { public static void main(String[] args) {
SpringApplication.run(HystrixRibbonApplication.class, args);
}
}

  c、修改RibbonServiceImpl.class的实现,在getPort方法上面加入@HystrixCommand注解,这样这个接口就有了熔断器功能了,其中@HystrixCommand中的fallbackMethod为执行快速失败的方法。

package com.cetc.service.impl;

import com.cetc.service.IRibbonService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate; @Service
public class RibbonServiceImpl implements IRibbonService { @Autowired
private RestTemplate restTemplate; @Override
@HystrixCommand(fallbackMethod = "error")
public Integer getPort() {
return restTemplate.getForObject("http://client/api/test/getPort", Integer.class);
} public Integer error() {
return 0
;
}

}

  d、测试。启动Eureka-Server、Eureka-Client、Hystrix-Ribbon端口分别为8670、8673、8677。

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  正常访问时:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  服务异常时:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  2)Feign中使用Hystrix(代码基于前面的Spring-Cloud之Feign声明式调用-4进行调整)

  a、因为Feign中自带了Hystrix功能,所以不需要重新加入依赖。

  b、在application.yaml中开启Hystrix的配置:

feign:
hystrix:
enabled: true

  c、编写TestHystrix服务错误的执行方式,继承Feign接口

package com.cetc.feign.hystrix;

import com.cetc.feign.client.TestFeign;
import org.springframework.stereotype.Component; @Component
public class TestHystrix implements TestFeign{ @Override
public Integer getPort() {
return 0;
}
}

  d、在@FeignClient中加入回调的class。

package com.cetc.feign.client;

import com.cetc.config.FeignConfiguration;
import com.cetc.feign.hystrix.TestHystrix;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping; @Component
@FeignClient(value = "client", configuration = {FeignConfiguration.class}, fallback = TestHystrix.class)
public interface TestFeign { @GetMapping("/api/test/getPort")
Integer getPort();
}

  e、测试、启动Eureka-Server、Eureka-Client、Hystrix-Feign端口分别为8670、8673、8678。

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  正常访问:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  服务器异常:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  六、Hystrix Dashboard监控熔断器的状态。

  在微服务架构中 ,为了保证服务实例的可用性,防止服务实例出现故障导致线程阻塞,而出现了熔断器模型 烙断器的状况反映了 个程序的可用性和健壮性,它是一个重要指标。Hystrix Dashboard 是监控 Hystrix 的熔断器状况的 个组件,提供了数据监控和 友好的图形化展示界面。

  1)Hystrix Dashboard和Ribbon结合使用(代码基于上面的熔断器代码编写)

  a、加入依赖

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
</dependency>

  说明:因为是监控所以加入actuator。hystrix为起步依赖这里需要。

  b、加入注解@EnableHystrixDashboard

package com.cetc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; @SpringBootApplication
@EnableEurekaClient
@EnableHystrix
@EnableHystrixDashboard
public class DashboardRibbonApplication { public static void main(String[] args) {
SpringApplication.run(DashboardRibbonApplication.class, args);
}
}

  c、加入相关配置到application.yaml,放开actuator的访问

management:
endpoints:
web:
exposure:
include: ["*"]

  d、测试。服务包含Eureka-Server、Eureka-Client、Dashboard-Ribbon。端口分别为8670、8673、8679

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  测试接口:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  访问:http://127.0.0.1:8679/hystrix

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  按照提示在输入框中对应链接:http://127.0.0.1:8679/actuator/hystrix.stream,点击Monitor Stream。测试效果

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  上面数字代表的意思如下:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  2)Hystrix Dashboard和Feign结合使用(代码基于上面的熔断器代码编写)

  a、加入依赖:

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
</dependency>

  说明:虽然Feign继承了hystrix,但那不是起步依赖说以这里还是需要hystrix的依赖

  b、加入注解:

package com.cetc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
@EnableHystrixDashboard
public class DashboardFeignApplication { public static void main(String[] args) {
SpringApplication.run(DashboardFeignApplication.class, args);
}
}

  说明:为什么还是需要加入@EnableHystrix的注解呢,在使用Dashboard的时候需要这个注解,不然会出现错误。

  c、修改application.yaml配置

feign:
hystrix:
enabled: true
management:
endpoints:
web:
exposure:
include: ["*"]

  d、测试。启动服务有Eureka-Server、Eureka-Client、Dashboard-Feign。端口分别为8670、8673、8680.

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  测试正常的接口:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  访问:http://127.0.0.1:8680/hystrix

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  按提示输入监控链接:http://127.0.0.1:8680/actuator/hystrix.stream,点击Monitor Stream。效果如下:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  数字代表的意义:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

   七、Turbine聚合监控。

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

  1)加入依赖:

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-turbine</artifactId>
</dependency>

  2)修改配置application.yaml

server:
port: 8681
eureka:
client:
service-url:
defaultZone:
http://127.0.0.1:8670/eureka/ # 实际开发中建议使用域名的方式
spring:
application:
name: turbine
turbine:
aggregator:
cluster-config: default
app-config: dashboard-ribbon,dashboard-feign
cluster-name-expression: new String("default")
management:
endpoints:
web:
exposure:
include: ["*"]

  说明:这里的turbine配置主要是加入服务app-config,两个服务均是之前写好的服务。

  3)编写启动项加入注解:

package com.cetc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine; @SpringBootApplication
@EnableEurekaClient
@EnableHystrixDashboard
@EnableTurbine
public class TurbineApplication { public static void main(String[] args) {
SpringApplication.run(TurbineApplication.class, args);
}
}

  4)测试。启动服务有Eureka-Server、Eureka-Client、Dashboard-Ribbon、Dashboard-Feign、Turbine。端口分别为8670、8673、8679、8680、8681.

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  测试正常服务访问:

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  打开:http://127.0.0.1:8681/hystrix

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  按照提示输入:http://127.0.0.1:8681/turbine.stream。点击Monitor Stream。效果如下

  Spring-Cloud之Hystrix熔断器-5-LMLPHP

  八、源码地址:https://github.com/lilin409546297/spring-cloud/tree/master/hystrix

05-11 19:30