当前位置: 首页 > news >正文

Hystrix——服务容错保护库

        熔断机制是解决微服务架构中因等待出现故障的依赖方响应而形成任务挤压最终导致自身服务瘫痪的一种机制,它的功能类似电路的保险丝,其目的是为了阻断故障,从而保护系统稳定性。Hystrix作为Spring Cloud中实现了熔断机制的组件,具有服务容错保护功能

Hystrix简介

什么是Hystrix?

概述:HystrixNetflix开源的一款针对分布式系统延迟和容错的库

作用:通过添加延迟容忍和容错逻辑,从而控制分布式服务之间的交互。

为什么用Hystrix?

        对于一个复杂的分布式系统,包含的应用可能多达数十个,这些应用有许多依赖项目,每个依赖项目在某个时刻不可避免会失败导致故障,如果不对这些故障进行隔离,整个分布式系统都可能会崩溃。

分布式系统中服务请求一切正常情况

分布式系统中服务有一个系统有延迟请求情况

分布式系统中其中有一个系统有延迟时,它可能阻塞整个用户请求:

分布式系统中服务高流量下请求情况 

高流量情况下,一个后端的依赖延迟可能会导致所有服务的资源在数秒内变的饱和,这也就意味着,后续如果再有请求将无法提供服务,应用会出现故障。比故障更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,从而备份队列、线程和其他资源,从而导致整个系统出现更多级联故障.如图:

分布式系统中Hystrix解决服务请求堵塞情况 

        Hystrix的出现就是为了解决上述问题的,它封装了每个依赖项,每个依赖项彼此隔离,当延迟发生时,它会被限制在资源中,并包含回退逻辑,该逻辑决定在依赖发生任何类型故障时应作出何种响应。

简单创建Hystrix工程

工作架构图:

1.创建eureka-server项目

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.7.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.xiaofen</groupId><artifactId>eureka-server</artifactId><version>0.0.1-SNAPSHOT</version><name>eureka-server</name><description>Demo project for Spring Boot with Eureka Server</description><properties><java.version>1.8</java.version><spring-cloud.version>Greenwich.SR2</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><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><!-- 如果需要,可以添加构建插件等配置 --><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.yml

server:port: 7000                                        # 服务器端口号7000
spring:application:                                      #端口号名称配置name: eureka-server
eureka:client:fetch-registry: false                           # 表示是否向Eureka Server注册register-with-eureka: false                     # 表示是否从Eureka Server获取注册信息service-url:defaultZone:http://${eureka.instance.hostname}:${server.port}/eureka/   #设置服务注册中心地址instance:hostname: localhost

启动类

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class, args);}}

2.创建eureka-hystrix-client项目

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.7.RELEASE</version><relativePath/></parent><groupId>com.xiaofeng</groupId><artifactId>eureka-hystrix-client</artifactId><version>0.0.1-SNAPSHOT</version><name>eureka-hystrix-client</name><description>Demo project for Spring Boot</description><url/><properties><java.version>1.8</java.version><spring-cloud.version>Greenwich.SR2</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><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-hystrix</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></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.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><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><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url></repository></repositories>
</project>

application.yml

server:port: 8764
spring:application:name: eureka-hystrix-client
eureka:client:service-url:defaultZone: http://localhost:7000/eureka/instance:hostname: localhost

启动类添加这几个注解:

config:

@Configuration
public class HystrixConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}
}

controller:

@RestController
public class HystrixController {@Autowiredprivate HystrixService hystrixService;@GetMapping("/hi")public String hi(String id){return hystrixService.hi(id);}
}

 service:

@Service
public class HystrixService {@Autowiredprivate RestTemplate restTemplate;@HystrixCommand(fallbackMethod = "hiError")public String hi(String id){return restTemplate.getForObject("http://hystrix-provider/hi?id="+id,String.class);}public String hiError(String id){return "此次调用进行服务降级,当前的id为:"+id;}
}

3.创建hystrix-provider项目

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.7.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.xiaofeng</groupId><artifactId>hystrix-provider</artifactId><version>0.0.1-SNAPSHOT</version><name>hystrix-provider</name><description>Demo project for Spring Boot</description><url/><properties><java.version>1.8</java.version><spring-cloud.version>Greenwich.SR2</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</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-test</artifactId><version>2.1.7.RELEASE</version><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.1.7.RELEASE</version></dependency></dependencies><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><!-- 如果需要,可以添加构建插件等配置 --><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

启动类:

@SpringBootApplication
@EnableEurekaClient
public class HystrixProviderApplication {public static void main(String[] args) {SpringApplication.run(HystrixProviderApplication.class, args);}}

controller:

@RestController
public class HystrixController {@RequestMapping("/hi")public String hi(String id){return "你好,访问接口成功,当前id为:"+id;}
}

4.项目测试

成功:

 

失败:

在Feign中使用Hystrix熔断器

开启Hystrix熔断

        Feign自带熔断功能,默认情况下,熔断功能是关闭的。如果要开启熔断,只需在配置文件中将hystrix.enabled设置为true即可。

        开启Hystrix熔断功能。在eureka-hystrix-client项目的配置文件application.yml中添加开启熔断的配置

feign:hystrix:enabled: true

         因为在Feign的起步依赖中引入了Hystrix依赖,所以在Feign中使用Hystrix不需要引入任何的依赖,只需要在配置文件中开启即可。

开启Feign Client功能

 eureka-hystrix-client的启动类中添加@EnableFeignClients开启Feign Client功能

修改项目中接口

        进入项目eureka-hystrix-client,在HystrixService接口上方的@FeignClient注解中,增加fallback属性配置,指定HystrixServiceImpl类为失败逻辑处理类

使用fallback属性指定的用于处理回退逻辑的类,必须实现@FeignClient注解修饰的接口。 

FeignHystrixServiceImpl实现了FeignHystrixService接口,并定义了一个hi()方法用于编写处理熔断的具体逻辑。这里,我们使用@Component注解修饰类FeignHystrixServiceImpl,其目的是将该类交给Spring容器管理。

controller

运行测试:

成功:

 失败:

 Hystrix工作原理

 Hystrix改为工作流程图

Hystrix的具体工作流程

1.实例化HystrixCommandHystrixObservableCommand对象

        第一步实例化HystrixCommandHystrixObservableCommand对象,是因为它们封装了对外部依赖访问的逻辑。

2.调用Command方法触发操作指令

        通过创建的HytrixCommandHystrixObservableCommand实例调用相关方法执行操作指令。Hystrix API提供了4个触发流程的方法供开发者调用,具体如下:

     1execute()方法:该方法是同步的,从依赖请求中接收到单个响应(或者出错时抛出异常)。

     2queue()方法:调用外部依赖只返回一个值,返回一个Future对象。

     3observe()方法:订阅一个从依赖请求中返回的Observable对象这个Observable对象包含了从依赖服务返回的结果。

     4toObservable()方法:返回一个Observable对象,只有当订阅一个从依赖请求中返回的Observable对象时,该方法才会执行Hystrix命令并返回结果。

3.根据依赖调用的缓存情况进行相应处理

        执行操作指令时,Hystrix首先会检查缓存内是否有对应指令的结果,如果有的话,将缓存的结果直接以Observable对象的形式返回

4.判断熔断器是否开启

        没有对应的缓存,Hystrix检查Circuit Breaker的状态。如果Circuit Breaker的状态为开启状态,Hystrix将不会执行对应指令,而是而是直接路由到第8步(Fallback),获取fallback方法,并执行fallback逻辑。

5.判断线程池/队列/信号资源是否已满

        如果Circuit Breaker状态为关闭状态,Hystrix会继续进行线程池、任务队列、信号量的检查(第5步),确认是否有足够的资源执行操作指令。如果资源满,Hystrix同样将不会执行对应指令,而是立即跳到第8,执行fallback逻辑

6.执行HystrixObservableCommand.construct()HystrixCommand.run()

如果资源充足,Hystrix将会执行操作指令操作指令的调用最终会到两个方法:

      1HystrixCommand.run(): 返回单个响应或者抛出异常。

      2HystrixObservableCommand.construct()返回一个发射响应的Observable   

         或者发送一个onError()的通知。

如果执行上述方法的执行时间大于命令所设置的超时时间值,那么该线程将会抛出一个TimeoutException异常在这种情况下,Hystrix将会路由到第8步,执行fallback逻辑,并且如果上述方法没有被取消或者中断,会丢弃这上述两个方法最终返回的结果。

如果命令最终返回了响应并且没有抛出任何异常,Hystrix在返回响应后会返回一些日志信息

     1如果是调用run()方法,Hystrix会返回一个Observable

     2如果是调用construct()方法,Hystrix会通过construct()方法返回  

          相同的Observable对象。

7.计算熔断器执行数据

Hystrix会报告成功、失败、拒绝和超时的指标给熔断器,熔断器包含了一系列的滑动窗口数据,并通过该数据进行统计。Hystrix使用这些统计数据来决定熔断器是否应该熔断,如果需要熔断,将在一定的时间内不再请求依赖(这个时间可以通过配置指定),当再一次检查请求的健康的话会重新关闭熔断器。

8.调用降级方法或者返回依赖请求的真正结果

 如果Hystrix命令执行成功,它将以Observable形式返回响应给调用者。根据第2)步的调用方式不同,在返回Observable之前可能会做一些转换

Dashboard监控熔断器状态

1.主要依赖pom.xml:

<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>

2.然后在原来项目基础上再添加开启DashBoard的注解:

@EnableHystrixDashboard

3.创建config包,config包下创建HystrixDashboardConfiguration,加入Hystrix.streamServlet配置。

@Configuration
public class HystrixDashboardConfiguration {@Beanpublic ServletRegistrationBean getServlet() {HystrixMetricsStreamServlet streamServlet = newHystrixMetricsStreamServlet();ServletRegistrationBean registrationBean = newServletRegistrationBean(streamServlet);registrationBean.setLoadOnStartup(1);registrationBean.addUrlMappings("/hystrix.stream");registrationBean.setName("HystrixMetricsStreamServlet");return registrationBean;}
}

 4.测试

 还有一个图形化界面http://localhost:8764/hystrix

点击按钮后进入这个界面:

标注的是服务的健康程度。

② 数字从上往下依次是消费者请求调用者的请求成功数、短路或熔断数和失败

的次数。

③ 数字从上往下依次是消费者请求调用者的超时数、线程池拒绝数和请求异常数。

④ 表示集群下的主机报告。

⑤ 表示消费者请求调用者的请求频率

http://www.lryc.cn/news/425494.html

相关文章:

  • 【区块链+金融服务】河北股权交易所综合金融服务平台 | FISCO BCOS应用案例
  • [图解]需要≠需求-《分析模式》漫谈
  • 刷到好听的音频怎么办
  • 怎么在网络攻击中屹立不倒
  • 详解 Python 中的面向对象编程(2)
  • 数据结构-线性表-顺序表
  • AI绘画大模型-StableDiffusion最强模型sd3(本地安装方法)
  • SpringBoot调用外部接口的几种方式
  • MySQL:information_schema查找某个表的主键是否在数据的其他位置出现之二
  • Linux进程和计划任务管理
  • 【Angular18】封装自定义组件
  • 【流媒体】RTMPDump—RTMP_ConnectStream(创建流连接)
  • MySQL学习3之锁机制
  • 2004-2023年上市公司过度负债数据(含原始数据+计算结果)
  • [机器学习]--KNN算法(K邻近算法)
  • 跨平台控制神器Escrcpy,您的智能生活助手
  • AR 眼镜之-开关机定制-实现方案
  • 论文阅读-Transformer Layers as Painters
  • 【STL】vector模拟实现
  • 静态成员static关键字
  • 本地项目git同步到线上
  • Allegro如何导入DXF结构文件并生成板框(1)?
  • Word密码忘记怎么办?三个密码找回工具帮你轻松找回密码
  • 使用 ABP 框架 (ASP.NET Boilerplate Project) 创建一个带有迁移功能的示例
  • WPF图表控件库
  • JAVA-WEB资源配置
  • 分享一个基于微信小程序的宠物服务中心的设计与实现(源码、调试、LW、开题、PPT)
  • 时空自回归模型(STAR)及 Stata 具体操作步骤
  • SpringCloud集成XXL-JOB定时任务
  • 《财经网》揭秘格行销量第一的秘籍!年销百万台,获千万级网红推荐!