目录
Hystrix
概念
作用
服务降级
简介
使用场景
接口降级
服务端服务降级
1.添加依赖
2.定义接口
3.实现接口
4.Controller类使用
5.启动类添加注释
6.浏览器访问
客户端服务降级
1.添加依赖
2.application.yml 中添加配置
3.定义接口
4.Controller类使用
5.appliction.yml 中添加配置,在客户端配置请求超时的时间
6.启动类添加注释
7.浏览器访问
全局降级
1.注解配置
2.创建方法
3.业务方法标注注解
4.浏览器访问
服务熔断
简介
熔断参数设置
熔断类型
熔断打开
熔断关闭
熔断半开
熔断机制
使用步骤
示例
1.定义接口
2.实现接口
3.方法对外提供服务
4.浏览器访问
故障监控
在微服务架构中,一个应用往往由多个服务组成,这些服务之间相互依赖,依赖关系错综复杂。
当服务 E 发生故障或网络延迟时,会出现以下情况:
1.即使其他所有服务都可用,由于服务 E 的不可用,那么用户请求 1、2、3 都会处于阻塞状态,等待服务 E 的响应。在高并发的场景下,会导致整个服务器的线程资源在短时间内迅速消耗殆尽
2.所有依赖于服务 E 的其他服务,例如服务 B、D 以及 F 也都会处于线程阻塞状态,等待服务 E 的响应,导致这些服务的不可用
3.所有依赖服务B、D 和 F 的服务,例如服务 A 和服务 C 也会处于线程阻塞状态,以等待服务 D 和服务 F 的响应,导致服务 A 和服务 C 也不可用
当微服务系统的一个服务出现故障时,故障会沿着服务的调用链路在系统中疯狂蔓延,最终导致整个微服务系统的瘫痪,这就是“雪崩效应”。为了防止此类事件的发生,微服务架构引入了“熔断器”的一系列服务容错和保护机制。
Hystrix
概念
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,可以保证一个服务出现故障时,不会导致整个系统出现雪崩效应,以提高分布式系统的弹性。
作为“断路器”,在一个服务出现故障时,可以通过短路器监控,返回一个可以处理的响应结果,保证服务调用线程不会被长时间占用,避免故障蔓延。
作用
保护线程资源:防止单个服务的故障耗尽系统中的所有线程资源
快速失败机制:当某个服务发生了故障,不让服务调用方一直等待,而是直接返回请求失败
提供降级(FallBack)方案:在请求失败后,提供一个设计好的降级方案,通常是一个兜底方法,当请求失败后即调用该方法
防止故障扩散:使用熔断机制,防止故障扩散到其他服务
监控功能:提供熔断器故障监控组件 Hystrix Dashboard,随时监控熔断器的状态
服务降级
简介
服务出现故障时,给故障服务降级到事先准备好的故障处理结果,将此结果返回给服务消费者;
如:
客户端访问服务1,服务1调用服务2,服务2出现故障,Hystrix服务降级,返回一个可以处理的结果给服务1,服务1再以友好的错误界面返回给客户端
使用场景
1.在服务器压力剧增时,根据实际业务情况及流量,对一些不重要、不紧急的服务进行有策略地不处理或简单处理,从而释放服务器资源以保证核心服务正常运作。
2.当某些服务不可用时,为了避免长时间等待造成服务卡顿或雪崩效应,而主动执行备用的降级逻辑立刻返回一个友好的提示,以保障主体业务不受影响
接口降级
服务端服务降级
1.添加依赖
<!--hystrix 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.定义接口
public interface DeptService {
// hystrix 熔断器示例 ok
public String deptInfo_Ok(Integer id);
//hystrix 熔断器超时案例
public String deptInfo_Timeout(Integer id);
}
3.实现接口
@Service("deptService")
public class DeptServiceImpl implements DeptService {
@Override
public String deptInfo_Ok(Integer id) {
return "线程池:" + Thread.currentThread().getName() + " deptInfo_Ok,id: " + id;
}
//一旦该方法失败并抛出了异常信息后,会自动调用 @HystrixCommand 注解标注的 fallbackMethod 指定的方法
@HystrixCommand(fallbackMethod = "dept_TimeoutHandler",
commandProperties =
//规定 5 秒钟以内就不报错,正常运行,超过 5 秒就报错,调用指定的方法
{@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")})
@Override
public String deptInfo_Timeout(Integer id) {
int outTime = 6;
try {
TimeUnit.SECONDS.sleep(outTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + " deptInfo_Timeout,id: " + id + " 耗时: " + outTime;
}
// 当服务出现故障后,调用该方法给出友好提示
public String dept_TimeoutHandler(Integer id) {
return "C语言中文网提醒您,系统繁忙请稍后再试!"+"线程池:" + Thread.currentThread().getName() + " deptInfo_Timeout,id: " + id;
}
}
@HystrixCommand 注解:
参数 fallbackMethod 属性用于指定降级方法
参数 execution.isolation.thread.timeoutInMilliseconds 用于设置自身调用超时时间的峰值,峰值内可以正常运行,否则执行降级方法
4.Controller类使用
@RestController
@Slf4j
public class DeptController {
@Autowired
private DeptService deptService;
@Value("${server.port}")
private String serverPort;
@RequestMapping(value = "/dept/hystrix/ok/{id}")
public String deptInfo_Ok(@PathVariable("id") Integer id) {
String result = deptService.deptInfo_Ok(id);
log.info("端口号:" + serverPort + " result:" + result);
return result + ", 端口号:" + serverPort;
}
// Hystrix 服务超时降级
@RequestMapping(value = "/dept/hystrix/timeout/{id}")
public String deptInfo_Timeout(@PathVariable("id") Integer id) {
String result = deptService.deptInfo_Timeout(id);
log.info("端口号:" + serverPort + " result:" + result);
return result + ", 端口号:" + serverPort;
}
}
5.启动类添加注释
@SpringBootApplication
@EnableEurekaClient //开启 Eureka 客户端功能
@EnableCircuitBreaker //激活熔断器功能
public class MicroServiceCloudProviderDeptHystrix8004Application {
public static void main(String[] args) {
SpringApplication.run(MicroServiceCloudProviderDeptHystrix8004Application.class, args);
}
}
6.浏览器访问
客户端服务降级
通常情况下,我们都会在客户端进行服务降级,当客户端调用的服务端的服务不可用时,客户端直接进行服务降级处理,避免其线程被长时间、不必要地占用
1.添加依赖
<!--hystrix 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.application.yml 中添加配置
application.yml 中添加以下配置,开启客户端的 Hystrix 功能
feign:
hystrix:
enabled: true #开启客户端 hystrix
3.定义接口
@Component
@FeignClient(value = "MICROSERVICECLOUDPROVIDERDEPTHYSTRIX")
public interface DeptHystrixService {
@RequestMapping(value = "/dept/hystrix/ok/{id}")
public String deptInfo_Ok(@PathVariable("id") Integer id);
@RequestMapping(value = "/dept/hystrix/timeout/{id}")
public String deptInfo_Timeout(@PathVariable("id") Integer id);
}
4.Controller类使用
@Slf4j
@RestController
public class HystrixController_Consumer {
@Resource
private DeptHystrixService deptHystrixService;
@RequestMapping(value = "/consumer/dept/hystrix/ok/{id}")
public String deptInfo_Ok(@PathVariable("id") Integer id) {
return deptHystrixService.deptInfo_Ok(id);
}
//在客户端进行降级
@RequestMapping(value = "/consumer/dept/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "dept_TimeoutHandler") //为该请求指定专属的回退方法
public String deptInfo_Timeout(@PathVariable("id") Integer id) {
String s = deptHystrixService.deptInfo_Timeout(id);
log.info(s);
return s;
}
// deptInfo_Timeout方法的 专用 fallback 方法
public String dept_TimeoutHandler(@PathVariable("id") Integer id) {
log.info("deptInfo_Timeout 出错,服务已被降级!");
return "C语言中文网提醒您:服务端系统繁忙,请稍后再试!(客户端 deptInfo_Timeout 专属的回退方法触发)";
}
}
5.appliction.yml 中添加配置,在客户端配置请求超时的时间
######################### Ribbon 客户端超时控制 ###################################
ribbon:
ReadTimeout: 6000 #建立连接所用的时间,适用于网络状况正常的情况下,两端两端连接所用的时间
ConnectionTimeout: 6000 #建立连接后,服务器读取到可用资源的时间
######################配置请求超时时间##########################
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 7000
####################配置具体方法超时时间 为 3 秒########################
DeptHystrixService#deptInfo_Timeout(Integer):
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
注意:
1.Hystrix 可以来为所有请求(方法)设置超时时间(单位为毫秒),若请求超时则触发全局的回退方法进行处理
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=mmm
2.Hystrix 还可以为某个特定的服务请求(方法)设置超时时间
hystrix.command.xxx#yyy(zzz).execution.isolation.thread.timeoutInMilliseconds=mmm
格式说明如下:
- xxx:为包含该服务方法的类的名称(通常为服务绑定接口的名称),例如 DeptHystrixService 接口。
- yyy:服务方法名,例如 deptInfo_Timeout() 方法。
- zzz:方法内的参数类型,例如 Integer、String 等等
- mmm:要设置的超时时间,单位为毫秒(1 秒 =1000 毫秒)
6.启动类添加注释
@SpringBootApplication
@EnableFeignClients //开启 OpenFeign 功能
@EnableHystrix //启用 Hystrix
public class MicroServiceCloudConsumerDeptFeignApplication {
public static void main(String[] args) {
SpringApplication.run(MicroServiceCloudConsumerDeptFeignApplication.class, args);
}
}
7.浏览器访问
全局降级
针对所有业务方法都配置降级方法,这极有可能会造成代码的急剧膨胀。为了解决该问题,我们还可以为所有业务方法指定一个全局的回退方法
1.注解配置
@Slf4j
@RestController
@DefaultProperties(defaultFallback = "dept_Global_FallbackMethod") //全局的服务降级方法
public class HystrixController_Consumer {
……
}
2.创建方法
创建一个名为 dept_Global_FallbackMethod 的全局回退方法
/**
* 全局的 fallback 方法,
* 回退方法必须和 hystrix 的执行方法在相同类中
* @DefaultProperties(defaultFallback = "dept_Global_FallbackMethod") 类上注解,请求方法上使用 @HystrixCommand 注解
*/
public String dept_Global_FallbackMethod() {
return "C语言中文网提醒您,运行出错或服务端系统繁忙,请稍后再试!(客户端全局回退方法触发,)";
}
降级(FallBack)方法必须与其对应的业务方法在同一个类中,否则无法生效
3.业务方法标注注解
在所有的业务方法上都标注 @HystrixCommand 注解,将 deptInfo_Timeout() 方法上的 @HystrixCommand(fallbackMethod = "dept_TimeoutHandler") 修改为 @HystrixCommand 即可
//在客户端进行降级
@RequestMapping(value = "/consumer/dept/hystrix/timeout/{id}")
@HystrixCommand
public String deptInfo_Timeout(@PathVariable("id") Integer id) {
String s = deptHystrixService.deptInfo_Timeout(id);
log.info(s);
return s;
}
全局降级方法的优先级较低,只有业务方法没有指定其降级方法时,服务降级时才会触发全局回退方法。若业务方法指定它自己的回退方法,那么在服务降级时,就只会直接触发它自己的回退方法,而非全局回退方法。
4.浏览器访问
服务熔断
简介
熔断机制是应对服务雪崩的一种链路保护机制,当服务出现故障时,服务会进行降级,熔断该服务节点,迅速返回错误响应信息。当检测到服务访问正常时,恢复其链路节点
熔断参数设置
①circuitBreaker.enabled:是否开启熔断;
②circuitBreaker.requestVolumeThreshold:当前服务失败几次后开启断路,默认20次;
③circuitBreaker.sleepWindowInMilliseconds:设置断路时间,过了该时间后会尝试恢复,在断路时间内,即使请求正确也会走降级方法;
熔断类型
在熔断机制中涉及了三种熔断类型:
熔断打开
熔断打开后,在此时间内不会对该服务进行调用,而是直接访问降级方法。通过设置熔断时间,当达到该时间后,会尝试恢复该服务
熔断关闭
熔断关闭代表服务正常,不会干扰正常服务调用。
熔断半开
熔断半开时,请求可以访问服务,若请求正常访问,则熔断会关闭;若请请求不正常,继续熔断,调用降级方法。
熔断机制
熔断机制是通过 Hystrix 实现的。Hystrix 会监控微服务间调用的状况,当失败调用到一定比例时(例如 5 秒内失败 20 次),就会启动熔断机制
使用步骤
1.当服务的调用出错率达到或超过 Hystix 规定的比率(默认为 50%)后,熔断器进入熔断开启状态。
2.熔断器进入熔断开启状态后,Hystrix 会启动一个休眠时间窗,在这个时间窗内,该服务的降级逻辑会临时充当业务主逻辑,而原来的业务主逻辑不可用。
3.当有请求再次调用该服务时,会直接调用降级逻辑快速地返回失败响应,以避免系统雪崩。
4.当休眠时间窗到期后,Hystrix 会进入半熔断转态,允许部分请求对服务原来的主业务逻辑进行调用,并监控其调用成功率。
5.如果调用成功率达到预期,则说明服务已恢复正常,Hystrix 进入熔断关闭状态,服务原来的主业务逻辑恢复;否则 Hystrix 重新进入熔断开启状态,休眠时间窗口重新计时,继续重复第 2 到第 5 步。
示例
1.定义接口
public interface DeptService {
// hystrix 熔断器示例 ok
public String deptInfo_Ok(Integer id);
//hystrix 熔断器超时案例
public String deptInfo_Timeout(Integer id);
// Hystrix 熔断机制案例
public String deptCircuitBreaker(Integer id);
}
2.实现接口
实现类 DeptServiceImpl 添加 deptCircuitBreaker() 的方法实现及其回退方法
//Hystrix 熔断案例
@Override
@HystrixCommand(fallbackMethod = "deptCircuitBreaker_fallback", commandProperties = {
//以下参数在 HystrixCommandProperties 类中有默认配置
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"), //是否开启熔断器
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "1000"), //统计时间窗
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //统计时间窗内请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠时间窗口期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"), //在统计时间窗口期以内,请求失败率达到 60% 时进入熔断状态
})
public String deptCircuitBreaker(Integer id) {
if (id < 0) {
//当传入的 id 为负数时,抛出异常,调用降级方法
throw new RuntimeException("c语言中文网提醒您,id 不能是负数!");
}
String serialNum = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t" + "调用成功,流水号为:" + serialNum;
}
//deptCircuitBreaker 的降级方法
public String deptCircuitBreaker_fallback(Integer id) {
return "c语言中文网提醒您,id 不能是负数,请稍后重试!\t id:" + id;
}
3.方法对外提供服务
// Hystrix 服务熔断
@RequestMapping(value = "/dept/hystrix/circuit/{id}")
public String deptCircuitBreaker(@PathVariable("id") Integer id){
String result = deptService.deptCircuitBreaker(id);
log.info("result:"+result);
return result;
}
4.浏览器访问
故障监控
Hystrix 还提供了准实时的调用监控功能,Hystrix 会持续地记录所有通过 Hystrix 发起的请求的执行信息,并以统计报表的形式展示给用户,包括每秒执行请求的数量、成功请求的数量和失败请求的数量等
1.添加依赖
<!--hystrix-dashboard 监控的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
2.application.yml 中添加配置
#http://eureka7001.com:9002/hystrix 熔断器监控页面
# localhost:8004//actuator/hystrix.stream 监控地址
hystrix:
dashboard:
proxy-stream-allow-list:
- "localhost"
3.主启动类上添加 @EnableHystrixDashboard 注解,开启 Hystrix 监控功能
@SpringBootApplication
@EnableHystrixDashboard
public class MicroServiceCloudConsumerDeptHystrixDashboard9002Application {
public static void main(String[] args) {
SpringApplication.run(MicroServiceCloudConsumerDeptHystrixDashboard9002Application.class, args);
}
}
4.创建配置类
@Configuration
public class HystrixDashboardConfig {
/**
* Hystrix dashboard 监控界面必须配置
* @return
*/
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");//访问路径
registrationBean.setName("hystrix.stream");
return registrationBean;
}
}
5.浏览器访问