这里写目录标题
系列文章目录
【Spring Cloud一】微服务基本知识
【Spring Cloud 三】Eureka服务注册与服务发现
【Spring Cloud 四】Ribbon负载均衡
【Spring Cloud 五】OpenFeign服务调用
背景
目前开发的项目其微服务之间的熔断处理方式使用的就是Hystrix的方式,为了更加的体会到它代码的便捷和高效,所以博主对Hystrix进行了再次学习和实践,加强对Hystrix的整体理解。
一、Hystrix是什么
Hystrix是Netflix开源的一款用于处理分布式系统故障容错 和延迟容错的工具。它提供了熔断器的功能,能够阻止分布式系统中出现级联故障。
服务雪崩
如下发的图所示:
- 用户去请求A服务,A服务web服务器会分配一个线程支持用户的访问
A发现需要完成用户的操作血药去调用B服务。 - A去请求B服务,B的web服务器也会分配一个线程支持A的访问
B发现需要完成A的操作需要去调用C。 - B去调用C但是C宕机了,B并不知道,还是一如既往的去调用C
- 导致A和B的线程都没有回收
但是此时又有大量请求进入A服务或者B服务,当将web容器的线程资源会被消耗完,服务就会瘫痪。服务A和服务B也就瘫痪了
这种由于一个服务出现故障,导致其余服务跟着产生故障,最后导致整个系统出现严重故障的现象就是服务雪崩 。
服务容错的相关概念
服务容错是确保系统在出现故障或异常情况继续保持可用性的一系列技术和方法。
熔断器
熔断器是一种防止故障蔓延的模式,在一个系统中,当其中一个服务发送故障的时候,熔断器会中断对该服务的请求,并返回预先设定的降级措施,从而防止对整个系统造成影响。
降级
降级是一种在服务发生故障时提供的备选响应的策略,确保用户在服务故障时依然能够得到响应。
超时控制
一个服务的响应时间可能因网络、资源等问题而增加。超时控制是指在发起请求后设置一个合理的超时时间,如果服务在规定时间内没有响应,就人物请求超时,并根据预定策略进行处理,如降级响应。
限流
限流是一种用于控制系统访问速率的策略,防止过多的请求同时涌入系统,导致系统过载而崩溃。通过限制请求的速率,可以保证系统在承受能力范围内稳定运行。
二、会什么要有Hystrix
为什么要有Hystrix,Hystrix解决了什么问题?
Hystrix在分布式系统中解决了故障容错、延迟容错、请求合并与缓存、实时监控、异常处理等问题,保证系统在出现故障是一眼能够保持可用性,防止级联故障的发生。
三、如何使用Hystrix进行熔断处理整体
整个系统中有三个服务,Eureka服务,一个服务提供者,一个服务消费者
如何搭建Eurka服务可以访问这篇博客【Spring Cloud 三】Eureka服务注册与服务发现
补充 :Hystrix是通过隔离服务的访问点阻止级联故障(熔断器Circuit Breaker ),并提供了故障的解决方案(服务降级FallBack),从而提高整个分布式系统的高可用。
项目代码
服务提供者
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.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wangwei</groupId>
<artifactId>rent-car-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rent-car-service</name>
<description>rent-car-service</description>
<properties>
<java.version>8</java.version>
<spring-cloud.version>Hoxton.SR12</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>
<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>
yml配置文件
yaml
server:
port: 8080
spring:
application:
name: rent-car-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
register-with-eureka: true #设置为fasle 不往eureka-server注册
fetch-registry: true #应用是否拉取服务列表到本地
registry-fetch-interval-seconds: 10 #为了缓解服务列表的脏读问题,时间越短脏读越少 性能相应的消耗回答
instance: #实例的配置
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
hostname: localhost #主机名称或者服务ip
prefer-ip-address: true #以ip的形式显示具体的服务信息
lease-renewal-interval-in-seconds: 10 #服务实例的续约时间间隔
启动类
java
@SpringBootApplication
@EnableEurekaClient
public class RentCarServiceApplication {
public static void main(String[] args) {
SpringApplication.run(RentCarServiceApplication.class, args);
}
}
controller
java
@RestController
public class RentCarController {
@GetMapping("rent")
public String rent(){
return "租车成功";
}
}
服务消费者
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.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wangwei</groupId>
<artifactId>customer-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>customer-service</name>
<description>customer-service</description>
<properties>
<java.version>8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</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-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</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>
yml配置文件
yaml
server:
port: 8081
spring:
application:
name: customer-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
register-with-eureka: true #设置为fasle 不往eureka-server注册
fetch-registry: true #应用是否拉取服务列表到本地
registry-fetch-interval-seconds: 10 #为了缓解服务列表的脏读问题,时间越短脏读越少 性能相应的消耗回答
instance: #实例的配置
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
hostname: localhost #主机名称或者服务ip
prefer-ip-address: true #以ip的形式显示具体的服务信息
lease-renewal-interval-in-seconds: 10 #服务实例的续约时间间隔
feign:
hystrix:
enabled: true # 开启熔断
启动类
java
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableCircuitBreaker //开启断路器
public class CustomerServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerServiceApplication.class, args);
}
}
feign
java
/**
* 这里需要制定熔断类
*/
@FeignClient(value = "rent-car-service",fallback = CustomerRentFeignHystrix.class)
public interface CustomerRentFeign {
@GetMapping("rent")
String rent();
}
hystrix
java
@Component
public class CustomerRentFeignHystrix implements CustomerRentFeign {
/**
* 这个方法是备选方案
* @return
*/
@Override
public String rent() {
return "备选方案";
}
}
controller
java
@RestController
public class CustomerController {
@Autowired
private CustomerRentFeign customerRentFeign;
@GetMapping("customerRent")
public String CustomerRent(){
System.out.println("客户来租车了");
String rent = customerRentFeign.rent();
return rent;
}
}
服务启动
先启动Eureka服务端再启动服务提供者最后启动服务消费者
当我们将服务提供者进行下线之后,服务消费者再调用服务提供者的时候,先进行了熔断,再执行了降级处理(执行备选方案)。
总结
- 以上就是Hystrix的基本使用,当服务出现故障时,开启熔断器执行降级方案。
- 后序博主会手动实现熔断器来加强对熔断器的理解。
- 由于Netflix已经宣布停止维护Hystrix,推荐使用Resilience4j或Sentinel等其他替代方案来处理容错和熔断问题。