微服务已经成当前各大大厂追求的主流技术架构,学习微服务前景非常可观,而SpringCloud已成为主流微服务技术栈。本系列文章将以SpringCloud技术栈进行精讲,全方位剖析讲解SpringCloud技术栈在微服务场景下的实战应用,可以点赞关注,后续持续为大家更新。
Spring Cloud Hystrix
知识索引
- 雪崩效应
- Hystrix介绍
- 案例演示
- 全局fallback
- Hystrix Dashboard监控平台
1 雪崩效应
分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务。如下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商品服务资源耗尽,无法继续对外提供服务。并且这种不可用可能沿请求调用链向上传递,这种现象被称为雪崩效应。
所以,如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就处在被拖垮的风险中。 因此,为了构建稳定、可靠的分布式系统,我们的服务应当具有自我保护能力,当依赖服务不可用时,当前服务启动自我保护功能,从而避免发生雪崩效应。
2 Hystrix介绍
Hystrix
,英文意思是豪猪,全身是刺,因其背上长满棘刺,从而拥有了自我保护的能力。。
Hystrix
是Netflix
开源的一款容错系统,同样具有自我保护能力。
Hystrix
用于隔离访问远程服务、第三方库、防止出现级联失败也就是雪崩效应
。
Hystrix
具有以下特性:
请求熔断:类似于电路中的保险丝,当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN).这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力。
服务降级:Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.告知后面的请求服务不可用了,不要再来了。
依赖隔离(采用舱壁模式,Docker就是舱壁模式的一种):在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池.比如说,服务A的两个不同的接口分别调用了服务B和服务C,假设服务B出现了阻塞,同时服务B在服务A中对应的接口被频繁调用,由于服务B的阻塞导致了资源在调用B时被耗尽,此时其他请求服务A中服务C对应的接口时也会出现阻塞,为了避免这种情况Hystrix允许针对不同的服务调用配置不同的线程池,用以进行依赖隔离,如服务A中针对服务B和服务C的调用都配置了50个线程的线程池。此时如果在调用服务A时发生了阻塞,那么不会耗尽所有资源,此时服务A中的调用服务B的接口依然可以对外提供服务。
请求缓存:比如一个请求过来请求我userId=1的数据,你后面的请求也过来请求同样的数据,这时我不会继续走原来的那条请求链路了,而是把第一次请求缓存过了,把第一次的请求结果返回给后面的请求。
请求合并:利用一个合并处理器,将对同一个服务发起的连续请求合并成一个请求进行处理(这些连续请求的时间窗默认为10ms),在这个过程中涉及到的一个核心类就是HystrixCollapser。
Spring Cloud Hystrix
是对Hystrix
的封装,使得在Spring Cloud
体系中使用Hystrix
的特性变得十分容易
3 案例演示
接下来我们在service-consumer
中演示Hystrix
如何使用
3.1 引入依赖
在service_consumer
的pom.xml
中引入
<!--熔断Hystrix starter-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
3.2 开启熔断
通过@EnableCircuitBreaker
注解开启熔断
/**
* Copyright (c) 2022 itmentu.com, All rights reserved.
*
* @Author: yang
*/
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
public class ServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumerApplication.class, args);
}
@Bean
@LoadBalanced//开启负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
3.3 开启服务降级
通过@HystrixCommand
注解标记允许降级处理的接口及降级方法。
@GetMapping("/hello-loadbanlance")
@HystrixCommand(fallbackMethod ="fallBackMethod")
public String hello2(){
// 1.通过注册中心的服务名构建url
String url = "http://service-provider/hello";
// 2.发送请求
return restTemplate.getForObject(url,String.class);
}
@GetMapping("/hello-feign")
@HystrixCommand(fallbackMethod ="fallBackMethod")
public String hello3(){
return helloFeign.hello();
}
// 熔断方法
public String fallBackMethod(){
return "fail";
}
代码说明:
1:@HystrixCommand注解用来标记一个可熔断的接口方法
2:fallbackMethod=““表示触发熔断后的快速响应结果
3:需注意熔断方法的返回值必须和@HystrixCommand标记的接口返回值相同
3.4 配置熔断策略
# 配置熔断策略:
hystrix:
command:
default:
circuitBreaker:
forceOpen: false # 强制打开熔断器 默认false关闭的
errorThresholdPercentage: 50 # 触发熔断错误比例阈值,默认值50%
sleepWindowInMilliseconds: 5000 # 熔断后休眠时长,默认值5秒
requestVolumeThreshold: 20 # 熔断触发最小请求次数,默认值是20
execution:
isolation:
thread:
timeoutInMilliseconds: 1000 # 熔断超时设置,默认为1秒
代码说明:
1:当Hystrix Command请求后端服务失败数量超过errorThresholdPercentage配置比例(默认50%),断路器会切换到开路状态(Open).
2:这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN).
3:这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN).
4:Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力。
3.5 测试
启动服务,调用
http://localhost:8002/consumer/hello-loadbanlance
http://localhost:8002/consumer/hello-feign
成功后,停止service-provider
实例再次调用触发熔断
4 全局fallback
在ConsumerController
上添加@DefaultProperties
注解,并通过defaultFallback
配置默认fallback
方法
@RestController
@RequestMapping("/consumer")
@DefaultProperties(defaultFallback="defaultFallBack")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private HelloFeign helloFeign;
@GetMapping("/hello")
public String hello(){
//1、获取Eureka中注册的provider-service实例列表
List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances("service-provider");
//2、获取实例
ServiceInstance serviceInstance = serviceInstanceList.get(0);
//3、根据实例的信息拼接的请求地址
String url = serviceInstance.getUri()+ "/hello";
//4、发送请求
return restTemplate.getForObject(url,String.class);
}
@GetMapping("/hello-loadbanlance")
@HystrixCommand
public String hello2(){
// 1.通过注册中心的服务名构建url
String url = "http://service-provider/hello";
// 2.发送请求
return restTemplate.getForObject(url,String.class);
}
@GetMapping("/hello-feign")
@HystrixCommand
public String hello3(){
return helloFeign.hello();
}
// 全局熔断方法
public String defaultFallBack(){
return "fail";
}
}
代码说明:
1:@DefaultProperties表示默认配置
2:该配置只会对和全局熔断方法返回值相同的接口方法生效
3:当配置了defaultFallback,@HystrixCommand中无需配置即可快速失败,当然也可以自行配置
5 Hystrix Dashboard监控平台
Hystrix
官方提供了基于图形化的DashBoard
(仪表板)监控平台。Hystrix
仪表板可以显示每个断路器(被@HystrixCommand
注解的方法)的状态。
5.1 pom依赖
<!--监控坐标-->
<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-dashboard</artifactId>
</dependency>
5.2 开启仪表板
/**
* Copyright (c) 2022 itmentu.com, All rights reserved.
*
* @Author: yang
*/
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
public class ServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumerApplication.class, args);
}
@Bean
@LoadBalanced//开启负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
5.3 配置文件
#暴露全部监控信息,可以只填写hystrix.stream,也可以暴露全部 * ,注意在yml文件中特殊符号需要加引号
management:
endpoints:
web:
exposure:
include: '*'
5.4 控制台
访问http://localhost:8002/hystrix,添加需要监控的服务http://localhost:8002/turbine/turbine.stream