在分布式微服务的项目中,常常会有多个服务复用,产生多个服务调用的情况。比如A服务调用B服务,B服务调用C服务。服务调用链路长了必然会增加服务超时的概率,服务的超时阻塞会一直占用线程资源,大量的阻塞会直接消耗完服务线程,严重情况下会导致服务直接宕机从而引发调用链路的服务雪崩。那么,有没有一种方式可以实现服务熔断、降低、隔离呢?今天我们介绍Netflix公司研发的Hystrix框架。
Hystrix是一个延迟和容错库,旨在隔离远程系统、服务和第三方库的访问点,停止级联故障,并在故障不可避免的复杂分布式系统中实现弹性。
服务熔断是在服务达到某些特定指标主动进行断开的一种操作,而服务降级则是在服务调用过程中对后续服务进行评估比如达到超时时间未响应就会进行后续冗余逻辑处理。服务熔断了必定会进行服务降级,但服务降级了并不一定是服务熔断触发。
服务雪崩是业务流程中多个服务进行链路调用,如果后续链路服务发生故障阻塞会影响调用方服务阻塞,严重情况下会直接将整个链路服务拖死,从而造成服务雪崩的现象。
Hystrix提供了信号量、线程两种隔离模式。信号量隔离直接可以限制服务的并发线程数目,而线程隔离则直接依靠线程池来限制当前负载直接使用当前线程池线程,从而避免消耗完服务的其他线程造成服务不可用的情况。默认情况下,Hystrix使用线程隔离,线程隔离才是真正意义上的服务隔离。
在实际的项目开发中,Hystrix与openfeign能够友好的集成。我们在Springboot、spring cloud项目中可以直接引入Hystrix、feign依赖,并且完成相应的配置即可达到我们需要的结果。
在微服务的开发中为了服务间的互相复用与调用,我们需要引入注册中心来帮助实现服的发布、订阅与维护。对于注册中心中间件的选择有nacos、consul等等,其中搭建都相对简单这里不再讲述。
当我们引入注册中心后我们直接可以使用feign框架通过RestTemplate直接调用服务,我们不再关心内部怎么调用,只需要按照特定的规则封装接口即可。
以下重点介绍Hystrix的相关集成和配置
org.springframework.boot
spring-boot-starter-parent
2.3.12.RELEASE
1.8
Hoxton.SR10
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
#hystrix
feign:
hystrix:
enabled: true
circuitbreaker:
enabled: true
hystrix:
threadpool:
#默认配置
default:
#动态调整线程数
allowMaximumSizeToDivergeFromCoreSize: false
#核心线程数
coreSize: 10
#最大线程数
maximumSize: 10
#空闲存活时间min
keepAliveTimeMinutes: 1
#队列长度 设置置为-1时,队列会使用 SynchronousQueue,此时其 size 为0,Hystrix 不会向队列内存放作业。
maxQueueSize: -1
#如果需要动态修改队列长度的话可以设置此值,即使队列未满,队列内作业达到此值时同样会拒绝请求。此值默认是 5
queueSizeRejectionThreshold: 5
command:
default:
#线程池key
threadPoolKeyOverride: default
#熔断器
circuitBreaker:
enabled: true
#错误占比
errorThresholdPercentage: 50
#窗口时间内最小请求数目
requestVolumeThreshold: 20
#休眠时间
sleepWindowInMilliseconds: 5000
execution:
#隔离
isolation:
strategy: THREAD
thread:
#线程超时时间
timeoutInMilliseconds: 5000
timeout:
enabled: true
#统计器
metrics:
rollingStats:
#窗口大小
timeInMilliseconds: 10000
#桶数目需要保证与timeInMilliseconds整除
numBuckets: 10
@EnableFeignClients
@EnableHystrix
@Slf4j
public class TestDemoApplication {
public static void main(String[] args) {
SpringApplication.run(TestDemoApplication.class, args);
}
}
/**
* @author senfel
* @version 1.0
* @date 2023/7/03 15:04
*/
@Service
@FeignClient(value = "test-demo",fallback = FallbackService.class)
public interface TestService {
/**
* 测试hystrix
*/
@GetMapping("/feign")
String feign(@RequestParam String str);
}
/**
* FallbackService
* @author senfel
* @version 1.0
* @date 2023/7/3 15:26
*/
@Service
public class FallbackService implements TestService {
@Override
public String feign(String str) {
return ">>>>>客户端服务降级>>>>>";
}
}
线程隔离、
服务调用超时5s降级、
10s内最低20个请求进入规则验证超过50%错误率直接熔断5s
@GetMapping("/feign")
@HystrixCommand(
// 标识线程池 保持唯一
threadPoolKey = "threadPoolKeyByFeign",
// 线程池细节属性配置
threadPoolProperties = {
// 线程数
@HystrixProperty(name="coreSize",value = "10"),
//最大线程数量
@HystrixProperty(name="maximumSize",value = "10"),
// 等待队列长度
@HystrixProperty(name="maxQueueSize",value="-1"),
//如果需要动态修改队列长度的话可以设置此值,即使队列未满,队列内作业达到此值时同样会拒绝请求。此值默认是 5
@HystrixProperty(name="queueSizeRejectionThreshold",value="5"),
//空闲时间1min
@HystrixProperty(name="keepAliveTimeMinutes",value="1")
},
// 熔断的一些细节属性配置
commandProperties = {
// 调用服务超时时间
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000"),
// 统计时间窗口定义
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "10000"),
//桶数量 保证与统计时间窗口整除
@HystrixProperty(name = "metrics.rollingPercentile.numBuckets",value = "10"),
// 统计时间窗口内的最小请求数
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "20"),
// 统计时间窗口内的错误数量百分比阈值
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),
// 自我修复时的活动窗口长度
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "5000")
},
// 降级方法
fallbackMethod = "myFallBack"
)
public String feign(String str){
if(str.contains("s")){
throw new RuntimeException();
}
return str+"ssss";
}
private String myFallBack(String str){
return ">>>>>服务端服务降级>>>>>";
}
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-starter-netflix-hystrix-dashboard
hystrix:
dashboard:
proxy-stream-allow-list: "127.0.0.1"
management:
endpoints:
web:
exposure:
include: health,hystrix.stream
http://127.0.0.1:9999/actuator/hystrix.stream
Springboot集成Hystrix实现熔断、降级、隔离较为简单,并且提供了hystrix-dashboard可视化仪表盘。Hystrix框架已经实现了熔断降级、隔离策略,我们集成后只需要根据自身情况进行配置选用即可。一般在微服务架构优先选择客户端熔断降级,当然也可在服务端进行注解配置。