一:简介
- 什么是Hystrix?
在分布式系统中,服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务会
出现故障,导致依赖于它们的其他服务出现远程调度的线程阻塞。Hystrix是Netflix公司开源的
一个项目,它提供了熔断器功能,能够阻止分布式系统中出现联动故障。Hystrix是通过隔离服
务的访问点阻止联动故障的,并且提供了故障的解决方案,从而提高了整个分布式系统的弹性。 - Hystrix的设计原则
⑴防止单个服务的故障耗尽整个服务的Servlet容器(例如Tomcat)的线程资源
⑵快速失败机制,如果某个服务出现了故障,则调用该服务的请求快速失败,而不是线程等待。
⑶提供回退方案,在请求出现故障时,提供设定好的回退方案。
⑷使用熔断机制,防止故障扩散到其他服务。
⑸提供熔断器的监控组件Hystrix Dashboard,可以实时监控熔断器的状态。 - Hystrix的工作机制
当我们一个请求通过API接口去访问另外一个服务应用的时候,在一定的时间内,如果我们的请求
失败的次数比较少的话(就是小于一定的数量),那么熔断器是会处于关闭状态的,不会被打开。当然
当我们的请求失败的次数达到一定的值时,那么Hystrix这个熔断器就会被打开,因为它判断我们调用的
这个服务应用肯定是出了问题,那么为了防止请求的线程不会一直处于阻塞状态,那么这时就会调用该
接口的快速失败的逻辑(即fallback回退的逻辑)。当然处于打开的熔断器过一段时间后,会处于半打开
状态,会将一部分的请求去尝试开开正常的逻辑调用是否能够执行成功,如果成功,说明调用的哪个服务
应用已经好了,这时熔断器就可以关闭了,否则继续关掉。
二:在RestTemplate和Ribbon上使用熔断器
- 一个父的服务类chapter5-2,里面都是前面章节需要创建的一些Demo服务应用
pom.xml文件内容:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.kgf</groupId> <artifactId>chapter5-2</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <name>chapter5-2</name> <!--继承一个父模块,然后再引入相应的依赖 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <!--relativePath是可选的,maven会首先搜索这个地址,在搜索本地远程repositories之前 --> <relativePath /> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java-version>1.8</java-version> <spring-cloud.version>Finchley.RELEASE</spring-cloud.version> </properties> <!--下面的方式通过import可以实现多继承的问题 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <modules> <module>eureka-server</module> <module>eureka-client</module> <module>eureka-ribbon-client</module> <module>eureka-feign-client</module> </modules> </project>
-
一个eureka-server服务应用,是用来服务注册的
⑴EurekaServerApplication.java启动类
⑵application.yml配置文件信息spring: profiles: active: dev #这里我们默认启用dev环境 --- spring: profiles: dev #环境一 server: port: 8761 eureka: instance: hostname: peer1 #环境一服务名 client: register-with-eureka: false fetch-registry: false --- spring: profiles: test #环境二 server: port: 8762 eureka: instance: hostname: peer2 #环境二服务名 client: service-url: #将peer2注册进入peer1 defaultZone: http://peer1:8761/eureka/
⑶pom.xml文件内容
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.kgf</groupId> <artifactId>chapter5-2</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>eureka-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-server</name> <dependencies> <!-- 引入eureka-server依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <!-- 引入test测试依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope><!--表示仅仅在测试的时候编译 --> </dependency> </dependencies> <build> <plugins> <!--能够将Spring Boot应用打包为可执行的jar或war文件,然后以通常的方式运行Spring Boot应用 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
-
一个eureka-client子服务,作为微服务的客户端,也就是微服务的提供者
⑴EurekaClientApplication.java启动类
⑵bootstrap.yml配置文件,这个里面存在两个环境,我们到时候需要启动两个提供者服务
⑶ HiController.java类
⑷pom.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.kgf</groupId> <artifactId>chapter5-2</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>eureka-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-client</name> <dependencies> <!-- 引入eureka依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 引入test测试依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope><!--表示仅仅在测试的时候编译 --> </dependency> </dependencies> <build> <plugins> <!--能够将Spring Boot应用打包为可执行的jar或war文件,然后以通常的方式运行Spring Boot应用 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
-
一个eureka-ribbon-client子服务,用来负载均衡调用上面的eureka-client服务的hi接口
⑴启动类EurekaRibbonClientApplication.java
⑵RibbonConfig.java用来注入RestTemplate的bean对象的类
⑶RibbonService.java调用eureka-client对外开发接口的类
⑷RibbonController.java类
⑸application.yml配置文件
⑹pom.xml文件<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.kgf</groupId> <artifactId>chapter5-2</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>eureka-ribbon-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-ribbon-client</name> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> </dependencies> </project>
-
测试,首先启动eureka-server,eureka-client,最后启动eureka-ribbon-client,注意我们在使用eclipse启动eureka-client时需要
指定选择哪个环境:如下
访问eureka-server服务,发现eureka-client和eureka-ribbon-client这两个服务都注册进来了
通过eureka-ribbon-client服务的接口去调用eureka-client服务
下面我们关闭eureka-client服务,让它处于不可用状态,那么eureka-ribbon-client就无法调用eureka-client
提供的“/hi”接口了,再次访问看看效果:
三:在Feign上使用熔断器
- 一个eureka-feign-client子服务,用来负载均衡调用上面的eureka-client服务的hi接口
⑴EurekaFeignClientApplication.java启动类
⑵EurekaClientFeignController.java层
⑶EurekaClientFeignService.java层
⑷EurekaClientFeign.java接口类,用来调用eureka-client服务的对外暴露的接口
⑸HiHystrixFallBack.java类
⑹application.yml配置文件
⑺pom.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.kgf</groupId> <artifactId>chapter5-2</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>eureka-feign-client</artifactId> <name>eureka-feign-client</name> <dependencies> <!--引入feign依赖,这个feign的起步依赖已经引入了Hystrix的依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
- 测试,首先启动eureka-server,eureka-client,最后启动eureka-feign-client
那么我们将eureka-client服务关掉看看效果:
四:使用Hystrix Dashboard监控熔断器的状态
- 简介
在微服务架构中,为了保证服务实例的可用性,防止服务实例出现故障导致线程阻塞,出现了
熔断器模型。熔断器的状况反映了一个程序的可用性和健壮性,它是一个重要指标。Hystrix Dashboard
是监控Hystrix的熔断器状况的一个组件,提供了数据监控和友好的图形化展示界面。Hystrix Dashboard
共支持三种不同的监控方式:
a:默认的集群监控:通过URL http://turbine-hostname:port/turine.stream开启,实现对默认集群的监控。
b:指定的集群监控:通过URL http://turbine-hostname:port/turine.stream?cluster=[clusterName]开启,
实现对clusterName集群的监控。
c:单体应用的监控:通过URL http://hystrix-app:port/hystrix.stream开启,实现对具体某个服务实例的监控。
注意:前两者需要整合Turbine才能实现对集群的监控,最后一个是对单个服务实例的监控。 - 在RestTemplate中使用Hystrix Dashboard
⑴修改子服务eureka-ribbon-client
a:在pom.xml文件中添加依赖
b:application.yml配置文件<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.kgf</groupId> <artifactId>chapter5-2</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>eureka-ribbon-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eureka-ribbon-client</name> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <!--hystrix-dashboard是用来监控Hystrix熔断器状况的一个组件 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency> <!-- spring boot提供了一系列的监控指标,可以通过actuator进行引入 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies> </project>
management.endpoints.web.exposure.include这个是用来暴露 endpoints 的。由于 endpoints 中会包含很多敏感信息, 除了 health 和 info 两个支持 web 访问外 ,其他的默认不支持 web 访问 .
c:EurekaRibbonClientApplication.java启动类
d:RibbonController.java类
e:RibbonService.java类
f:RibbonConfig.java类
⑵测试,首先启动eureka-server,eureka-client,最后启动eureka-ribbon-client
a:在浏览器上访问http://localhost:8764/hystrix/
b:在浏览器访问http://localhost:8764/actuator/hystrix.stream,注意:这里需要先调用过一些hystrix接口 否则会出现一只ping的现象
调用一下hystrix接口
再次查看
c:测试仪表盘
d:图形各个元素的含义(这是网上找的一个图形解释)
- 在feign中使用Hystrix Dashboard
⑴修改子服务eureka-feign-client
a:修改application.yml文件
b:EurekaFeignClientApplication.java启动类
c:EurekaClientFeignController.java类
d:EurekaClientFeignService.java类
e:EurekaClientFeign.java接口类
f:HiHystrixFallBack.java类
g:pom.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.kgf</groupId> <artifactId>chapter5-2</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>eureka-feign-client</artifactId> <name>eureka-feign-client</name> <dependencies> <!--引入feign依赖,这个feign的起步依赖已经引入了Hystrix的依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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-netflix-hystrix-dashboard</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-netflix-hystrix</artifactId> </dependency> </dependencies> </project>
⑵ 测试和上面的restTemplate一样即可。
注意:feign整合这个hystrixdashboard必须有下面的3个依赖