SpringCloud Netflix Hystrix熔断容错降
2020-11-12 本文已影响0人
kaixingdeshui
SpringCloud Netflix Hystrix熔断容错降级
现象:
在微服务中,一个请求有可能是多个微服务协同处理,请求一旦大量被阻塞,会占用大量资源,有可能会使整个系统雪崩。
为了防止出现这种现象,需要一种机制来处理请求堆积情况,出现了Hystrix。
Hystrix的构建思路:
1.服务限流:服务消费者限制自身对某一服务能够发起的并发请求数量,超过数量则不调用
2.服务熔断:熔断状态下,服务消费者不会发起对某一服务的调用
3.服务降级:请求异常的情况下,程序执行指定的降级策略
官方文档介绍:
https://www.springcloud.cc/spring-cloud-netflix.html
Hystrix 集成
1.pom导入依赖
<!--hystrix 熔断容错-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
实现方式一:
继承HystrixCommand,重写run,getFallback方法:
/**
* hystrix 熔断容错机制
*/
public class CustomerCommand extends HystrixCommand<Object> {
private RestTemplate restTemplate;
public CustomerCommand(RestTemplate restTemplate) {
// super(setter);
super(//也可以在配置文件里配置信息
Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("study-hystrix"))
.andCommandKey(HystrixCommandKey.Factory.asKey("CustomerController"))
//定义线程池
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("studyThreadPool"))
.andCommandPropertiesDefaults(
HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(100)//执行超时时间100ms
.withCircuitBreakerSleepWindowInMilliseconds(5000))//熔断时间5s
.andThreadPoolPropertiesDefaults(
HystrixThreadPoolProperties.Setter().withCoreSize(1).withMaxQueueSize(1))
);
this.restTemplate = restTemplate;
}
@Override
protected Object run() throws Exception {
System.out.println("当前线程:"+Thread.currentThread().getName());
//核心实现,调用方法
Object result = restTemplate.getForObject("http://hello-server/client_1",String.class,"");
return result;
}
@Override
protected Object getFallback() {
System.out.println("降级处理");
return "返回降级结果";
}
}
在controller里直接创建调用:
@RestController
public class CustomerController {
@Autowired
private RestTemplate restTemplate;
/**
*第一种方式实现降级:通过继承HystrixCommand,重写run,getFallback方法
* @return
*/
@GetMapping("/test")
public Object test(){//超时降级处理
return new CustomerCommand(restTemplate).execute();
}
}
application配置信息
server:
port: 8003
spring:
application:
name: hystrix-demo
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
第二种方式:
通过注解的方式
@RestController
public class CustomerController {
@Autowired
private RestTemplate restTemplate;
/**
* 第二种方式实现降级:用注解的方式
* 需要在application入口加
* //熔断注解
* @EnableCircuitBreaker
*fallbackMethod :定义降级执行的方法名
* @return
*/
@GetMapping("/test2")
@HystrixCommand(fallbackMethod = "callTimeOutFallBack",
threadPoolProperties =
{@HystrixProperty(name = "coreSize",value = "1"),
@HystrixProperty(name = "queueSizeRejectionThreshold",value = "1")},
commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "100")})
public Object getTest2(){//超时降级处理
return restTemplate.getForObject("http://hello-server/client_1",String.class,"");
}
public Object callTimeOutFallBack(){
return "请求test2 降级";
}
}
在程序入口加上EnableCircuitBreaker注解
@SpringBootApplication
@EnableEurekaClient
//熔断注解
@EnableCircuitBreaker
public class LearnHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(LearnHystrixApplication.class, args);
}
}
Hystrix资源隔离
不管是注解还是继承HystrixCommand,都是在线程池里执行,确保资源隔离。
image.png
初始化过程
HystrixCommand 的父类 AbstractCommand 构造方法做初始化:
image.png
//命令分组名称(服务名)
this.commandGroup = initGroupKey(group);
//命令名称(接口/业务)
this.commandKey = initCommandKey(key, getClass());
//加载配置
this.properties = initCommandProperties(this.commandKey, propertiesStrategy, commandPropertiesDefaults);
this.threadPoolKey = initThreadPoolKey(threadPoolKey,
this.commandGroup, this.properties.executionIsolationThreadPoolKeyOverride().get());
//度量器。收集命令执行的数据收集和统计
this.metrics = initMetrics(metrics, this.commandGroup,
this.threadPoolKey, this.commandKey, this.properties);
//熔断器
this.circuitBreaker = initCircuitBreaker(this.properties.circuitBreakerEnabled().get(), circuitBreaker, this.commandGroup, this.commandKey, this.properties, this.metrics);
//线程池,资源隔离
this.threadPool = initThreadPool(threadPool, this.threadPoolKey, threadPoolPropertiesDefaults);
执行流程
HystrixCommand.execute()返回一个Future对象:
image.png通过Observable 观察者模式实现发布订阅消费事件
image.png
terminateCommandCleanup
unsubscribeCommandCleanup
applyHystrixSemantics
image.png
度量计数
image.png
线程池执行applyHystrixSemantics--> executeCommandAndObserve->
executeCommandWithSpecifiedIsolation->threadPool.getScheduler
image.png
Hystrix 可视化监控
- pom导入依赖
<!--web-->
<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-dashboard</artifactId>
</dependency>
2.添加注解
/**
* 可视化网页
* http://localhost:9999/hystrix
*/
@SpringBootApplication
//启用hystrix 可视化
@EnableHystrixDashboard
public class LearnDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(LearnDashboardApplication.class, args);
}
}
3.application配置
server:
port: 9999
spring:
application:
name: dashboard-demo
hystrix:
dashboard:
proxy-stream-allow-list: "*"
image.png
在需要开放监控的项目中配置监控端点:
#dashboard端点监控
management:
endpoints:
web:
exposure:
include: "*"
image.png