SpringCloud-服务降级_服务熔断_服务限流(Hystrix)
Hystrix
https://github.com/Netflix/Hystrix/
概述
前言
分布式系统面临的问题
复杂的分布式体系结构的应用 可能有很多个依赖,每个依赖在某些时刻将不可避免的失败;
服务雪崩

what
1、Hystrix是一个 处理分布式系统的延迟/容错的 开源库;
2、在分布式系统里,许多依赖不可避免的会调用失败(超时、异常...),Hystrix能保证在一个依赖出现异常的情况下,不会导致服务整体失败,避免级联故障,保证分布式系统的弹性;
3、"断路器"本身是一种开关,当某个服务单元发生故障时,通过断路器的故障检测 向调用方 返回一个符合预期、备选的FallBack,而不是长时间的等待或抛出调用方无法处理的异常;
这样保证了服务调用方的线程 不会被长时间占用,从而避免故障在分布式系统中蔓延,乃至雪崩;
停更维护怎么办

解决

resilience4j、
Hystrix概念
服务降级
what
当服务不可用时,给调用方的兜底响应;
什么情况会发生服务降级?
程序异常、超时、服务熔断触发服务降级、线程池满
服务熔断
what
当服务达到峰值,直接拒绝访问,给调用方一个兜底响应;
服务限流
what
当服务突然接收到大量请求时,限制单位时间内可处理的数量;
主要的问题
超时导致服务变慢
解决
超时不再继续等待
出错(服务宕机/程序出错)
解决
出错有兜底
解决方案
1、服务提供方超时/运行报错/宕机 -> 调用方不能卡死等待,必须有服务降级;
2、服务提供方正常,调用方自己故障/有自己要求(自己等待时间<服务提供方时间) -> 调用方自己服务降级;
How
服务降级
一般服务降级用在 服务调用方;
服务提供方
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
@EnableCircuitBreaker // 开启Hystrix
@EnableEurekaClient
@SpringBootApplication
public class HystrixPaymentStarter8001 {
public static void main(String[] args) {
SpringApplication.run(HystrixPaymentStarter8001.class, args);
}
}
@RestController
public class Controller {
@Autowired
PaymentService paymentService;
@HystrixCommand(fallbackMethod = "timeOutFallback", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})
@GetMapping(value = "/hystrix/timeout")
public String timeout(){
int i = 1/0; // 运行报错
return paymentService.timeout(); // 服务超时
}
/**
* 服务降级 Fallback方法
* @return
*/
public String timeOutFallback(){
return Thread.currentThread().getName() + "payment系统繁忙,请稍后再试! o(╥﹏╥)o";
}
}
服务调用方
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
#开启Feign的Hystrix
feign:
hystrix:
enabled: true
@EnableHystrix // 开启Hystrix
@EnableFeignClients // 开启Feign支持
@SpringBootApplication
public class OpenFeignHystrixOrderStarter80 {
public static void main(String[] args) {
SpringApplication.run(OpenFeignHystrixOrderStarter80.class, args);
}
}
@RestController
public class OrderController {
@Autowired
private PaymentService paymentService;
@HystrixCommand(fallbackMethod = "timeOutFallback", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
})
@GetMapping(value = "/order/timeout")
public String timeOut(){
int a = 1/0; // 程序运行报错
return paymentService.timeOut();
}
/**
* 服务降级 Fallback方法
* @return
*/
public String timeOutFallback(){
return Thread.currentThread().getName() + "由于 payment系统繁忙,请稍后再试! o(╥﹏╥)o";
}
}
全局Fallback
标记@HystrixCommand方法才会进行服务降级:
有自定义的fallbackMethod,按自定义处理;
无自定义的fallbackMethod,按全局处理;
@DefaultProperties(defaultFallback = "globalFallback") // 全局fallback定义
@RestController
public class OrderController {
@Autowired
private PaymentService paymentService;
@HystrixCommand // 全局服务降级
@GetMapping(value = "/order/ok")
public String ok(){
int a = 1/0; // 程序运行报错
return paymentService.ok();
}
@HystrixCommand(fallbackMethod = "timeOutFallback", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
})
@GetMapping(value = "/order/timeout")
public String timeOut(){
int a = 1/0; // 程序运行报错
return paymentService.timeOut();
}
/**
* 服务降级 Fallback方法
* @return
*/
public String timeOutFallback(){
return Thread.currentThread().getName() + "由于 payment系统繁忙,请稍后再试! o(╥﹏╥)o";
}
/**
* 服务降级 globalFallback方法
* @return
*/
public String globalFallback(){
return Thread.currentThread().getName() + "全局Fallback payment系统繁忙,请稍后再试! o(╥﹏╥)o";
}
}
fallback方法与业务代码解耦
#开启Feign的Hystrix
feign:
hystrix:
enabled: true
@Component
public class PaymentFallbackService implements PaymentService{
@Override
public String ok() {
return "PaymentFallbackService.ok O(∩_∩)O";
}
@Override
public String timeOut() {
return "PaymentFallbackService.timeOut O(∩_∩)O";
}
}
@Component
@FeignClient(value = "eureka-hystrix-payment-service", fallback = PaymentFallbackService.class)
public interface PaymentService {
@GetMapping(value = "/hystrix/ok")
String ok();
@GetMapping(value = "/hystrix/timeout")
String timeOut();
}
@RestController
public class OrderController {
@Autowired
private PaymentService paymentService;
@GetMapping(value = "/order/ok")
public String ok(){
return paymentService.ok();
}
}
@EnableHystrix // 开启Hystrix
@EnableFeignClients // 开启Feign支持
@SpringBootApplication
public class OpenFeignHystrixOrderStarter80 {
public static void main(String[] args) {
SpringApplication.run(OpenFeignHystrixOrderStarter80.class, args);
}
}
服务熔断
https://martinfowler.com/bliki/CircuitBreaker.html
熔断机制是什么

应对雪崩效应的 一种微服务链路保护机制;
当扇出链路的某个微服务不可用或响应时间过长,进行服务降级,进而熔断该节点微服务的调用,快速返回错误的响应信息;
当检测到该节点微服务调用正常后,恢复调用链路;
实现
在SpringCloud中,使用Hystrix实现;
Hystrix会监控微服务之间的调用情况,当失败的调用达到一定的阈值,缺省是5秒内20次失败,就会启动熔断机制;
Hystrix服务熔断机制注解 @HystrixCommand;
How
服务降级 -> 服务熔断 -> 恢复服务
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
server:
port: 8001
spring:
application:
name: eureka-hystrix-payment-service
eureka:
client:
register-with-eureka: true #是否向注册中心注册自己
fetchRegistry: true #是否从注册中心抓取已有的注册信息 默认true,集群必须设置为true
service-url:
defaultZone: http://localhost:7001/eureka/ #单机版
@EnableCircuitBreaker // 开启Hystrix
@EnableEurekaClient
@SpringBootApplication
public class HystrixPaymentStarter8001 {
public static void main(String[] args) {
SpringApplication.run(HystrixPaymentStarter8001.class, args);
}
}
package com.an;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
/**
* @author apy
* @description
* @date 2022/8/5 10:57
*/
@RestController
public class Controller {
// 服务熔断
@HystrixCommand(fallbackMethod = "circuitBreakerFallback", commandProperties = {
// 在10s访问时间内,进行10次访问,失败率达到60%后,进行熔断
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"), // 是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), // 请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 时间窗口期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60") // 失败率达到多少后跳闸
})
@GetMapping(value = "/hystrix/circuitBreaker/{id}")
public String circuitBreaker(@PathVariable(value = "id") Long id){
if (id < 0){
throw new IllegalArgumentException("param error");
}
return Thread.currentThread().getName() + "success";
}
/**
* 服务降级 Fallback方法
* @param id
* @return
*/
public String circuitBreakerFallback(Long id){
return "circuitBreakerFallback...id:"+ id;
}
}
熔断类型
Open:
请求不再调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设时钟进入HalfOpen状态;
不会调用主逻辑,直接调用降级fallback;
Half Open:
部分请求根据规则调用当前服务,如果请求成功且符合规则,任务当前服务恢复正常,关闭熔断;
Close:
不会对服务进行熔断;
服务限流
...
Hystrix工作流程
https://github.com/Netflix/Hystrix/wiki/How-it-Works
Hystrix图形化Dashboard
what
Hystrix还提供了 图形化Dashboard,会持续记录所有通过Hystrix发起的请求的执行信息,并以图形报表的形式展示;
Netflix通过hystrix-metrics-event-stream实现了以上监控;
SpringCloud也整合了Hystrix Dashboard,对监控内容转化为图形化界面;
How
Hystrix Dashboard
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
server:
port: 9001
@EnableHystrixDashboard
@SpringBootApplication
public class HystrixDashboardStarter9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardStarter9001.class, args);
}
}
http://localhost:9001/hystrix
Hystrix Dashboard监控8001微服务
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> 被监控的服务必须的依赖
</dependency>
@EnableCircuitBreaker // 开启Hystrix
@EnableEurekaClient
@SpringBootApplication
public class HystrixPaymentStarter8001 {
public static void main(String[] args) {
SpringApplication.run(HystrixPaymentStarter8001.class, args);
}
/**
* 为服务监控而配置,与容错本身无关;
* @return
*/
@Bean
public ServletRegistrationBean getServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
bean.setLoadOnStartup(1);
bean.addUrlMappings("/hystrix.stream");
bean.setName("HystrixMetricsStreamServlet");
return bean;
}
}
浙公网安备 33010602011771号