一、分布式系统面临的问题
- 在微服务架构体系下,服务间的调用错综复杂,交织成一张大网。如果其中某个节 点突然无法正常工作,则访问它的众多服务都会被卡住,进而有更多服务被卡住,系统 中的线程、CPU、内存等资源有可能被迅速耗尽,最终整个服务体系崩溃。
-
二、Hystrix介绍
Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多 依赖不可避免的会调用失败,比如超时、异常等,Hystrix 能够保证在一个依赖出问题的 情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
- “断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故 障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应 (FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服 务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延, 乃至雪崩。
Hytrix 能够提供服务降级、服务熔断、服务限流、接近实时的监控等方面的功能。
三、服务熔断机制
熔断机制是应对雪崩效应的一种微服务链路保护机制。 当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该 节点微服务的调用,快速响应错误信息。当检测到该节点微服务调用响应正常后恢复调用链 路。在 SpringCloud 框架里熔断机制通过 Hystrix 实现。Hystrix 会监控微服务间调用的状况, 当失败的调用到一定阈值,缺省是 5 秒内 20 次调用失败就会启动熔断机制。熔断机制的注 解是@HystrixCommand。
三、熔断-代码部分
熔断指的是provider方的熔断,如果provider方出现的问题,熔断后别的就不在调用这个方法。
1. 在provider工程中添加依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>
2. 在provider主启动类上添加 @EnableCircuitBreaker 注解
/*** @date: 2021/2/28 15:33* @author: 易学习* 下面两个注解功能大致相同,但是这个版本不需要添加* @EnableDiscoveryClient: 启用发现服务功能,不局限于Eureka注册中心* @EnableEurekaClient: 启用Eureka客户端功能,必须是Eureka注册中心** @EnableCircuitBreaker: 启用断路器功能【服务熔断】*/@EnableCircuitBreaker@SpringBootApplicationpublic class ApplicationProvider {public static void main(String[] args) {SpringApplication.run(ApplicationProvider.class);}}
3. 在common 工程中添加一个 ResultEntity ,统一作为AJAX请求和远程服务调用返回值
package com.atguigu.spring.cloud.util;/*** 整个项目统一使用这个类型作为Ajax请求或远程方法调用返回响应的数据格式* @author** @param <T>*/public class ResultEntity<T> {public static final String SUCCESS = "SUCCESS";public static final String FAILED = "FAILED";public static final String NO_MESSAGE = "NO_MESSAGE";public static final String NO_DATA = "NO_DATA";/*** 操作成功,不需要返回数据* @return*/public static ResultEntity<String> successWithoutData() {return new ResultEntity<String>(SUCCESS, NO_MESSAGE, NO_DATA);}/*** 操作成功,需要返回数据* @param data* @return*/public static <E> ResultEntity<E> successWithData(E data) {return new ResultEntity<>(SUCCESS, NO_MESSAGE, data);}/*** 操作失败,返回错误消息* @param message* @return*/public static <E> ResultEntity<E> failed(String message) {return new ResultEntity<>(FAILED, message, null);}private String result;private String message;private T data;public ResultEntity() {}public ResultEntity(String result, String message, T data) {super();this.result = result;this.message = message;this.data = data;}@Overridepublic String toString() {return "ResultEntity [result=" + result + ", message=" + message + ", data=" + data + "]";}public String getResult() {return result;}public void setResult(String result) {this.result = result;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}}
4. provider工程中的controller方法
/*** @HystrixCommand 注解通过 fallbackMethod属性指定断路情况下要调用的备用方法* @param name* @return*/@HystrixCommand(fallbackMethod= "getUserBackUp")@RequestMapping("/provider/get/user")public ResultEntity<User> getUser(@RequestParam String name){// 如果这个方法出现 错误/超时 就会去 备用方法 【超时默认为1秒】return ResultEntity.successWithData(new User(1,"aaa","男"));}/*** 备选方案* @param name* @return*/public ResultEntity<User> getUserBackUp(@RequestParam String name){return ResultEntity.failed("熔断机制触发!");}
5.注意:
- 这只是熔断部分,没有远程调用,所以不用在common的service中写同名接口
- 浏览器访问的时候直接访问provider的controller【测试】
四、服务降级机制
- 服务降级处理时在客户端(consumer端)实现完成的,和provider没有关系。
- 当某个Consumer访问一个provider却迟迟得不到响应时预先设定好一个解决方案,而不是一直等待。

1.common工程添加 Hystrix依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>
2. common工程中需要定义一个工厂类
实现 FallbackFactory 接口【泛型为Common中的远程调用Service】
/*** @date: 2021/3/5 21:36* @author: 易学习* 1.实现Consumer端服务降级的功能* 2.实现FallbackFactory接口时要传入@FeignClient接口类型* 3.在create()方法中返回一个@FeignClient注解标注的接口类型的对象,当Provider调用失败后,会执行这个对象的对应方法*/@Componentpublic class MyFallBackFactory implements FallbackFactory<UserRemoteService> {@Overridepublic UserRemoteService create(Throwable throwable) {return new UserRemoteService() {@Overridepublic ResultEntity<User> getUser(String name) {return ResultEntity.failed("consumer端降级!!");}};}}
3. 修改common的远程 调用接口
common工程中原来的远程调用接口 UserRemoteService 的@FeignClients要添加 FallbackFactory属性为自己写的工厂.class
fallbackFactory属性指定provider不可用时提供备用方案的工厂对象
4.feign-consumer端启动hystrix
【在配置文件中启动】
feign:hystrix:enabled: true
