官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/1.3.5.RELEASE/single/spring-cloud-netflix.html#_circuit_breaker_hystrix_clients
我们知道,微服务之间是可以进行相互调用的,那么如果出现了下面的情况会导致什么问题?
由于位于最底端的服务提供者E发生故障,那么此时会直接导致服务ABCD全线崩溃,就像雪崩了一样。
这种问题实际上是不可避免的,由于多种因素,比如网络卡顿、系统故障、硬件问题等,都存在一定可能,会导致这种极端的情况发生。因此,我们需要寻找一个应对这种极端情况的解决方案。
为了解决分布式系统的雪崩问题,SpringCloud 提供了 Hystrix 熔断器组件,他就像我们家中的保险丝一样,当电流过载就会直接熔断,防止危险进一步发生,从而保证家庭用电安全。可以想象一下,如果整条链路上的服务已经全线崩溃,这时还在不断地有大量的请求到达,需要各个服务进行处理,肯定是会使得情况越来越糟糕的。
我们来详细看看它的工作机制:
首先我们来看看服务降级,注意一定要区分开服务降级和服务熔断的区别,服务降级并不会直接返回错误,而是可以提供一个补救措施,正常响应给请求者。这样相当于服务依然可用,但是服务能力肯定是下降了的。
我们就基于借阅管理服务来进行讲解,我们不开启用户服务和图书服务,表示用户服务和图书服务已经挂掉了。
①我们在 borrowservice 模块中导入 Hystrix 的依赖 (Hystrix已经停止维护,SpringCloud 依赖中已经不自带了,所以需要单独导入)
org.springframework.cloud spring-cloud-starter-netflix-hystrix 2.2.10.RELEASE
②接着我们需要在启动类添加@EnableHystrix
注解开启:
@SpringBootApplication
@EnableHystrix //启用Hystrix
public class BorrowApplication {public static void main(String[] args) {SpringApplication.run(BorrowApplication.class, args);}
}
由于用户服务和图书服务不可用,所以查询借阅信息的请求肯定是没办法正常响应的。
③这时我们使用@HystrixCommand
注解选择一个备选方案,也就是说当服务出现异常时,返回我们的备选方案:
@RestController
public class BorrowController {@Resourceprivate BorrowService borrowService;@HystrixCommand(fallbackMethod = "onError") //使用 @HystrixCommand 来指定备选方案@GetMapping("/borrow/{uid}")public UserBorrowView findUserBorrows(@PathVariable("uid") int uid) {return borrowService.getBorrowViewByUid(uid);}// 注意参数和返回值要和上面的一致public UserBorrowView onError(int uid) {// 备选方案,这里直接返回空列表了return new UserBorrowView(null, Collections.emptyList());}
}
④可以看到,虽然我们的服务无法正常运行了,但是依然可以给浏览器正常返回响应数据:
服务降级是一种比较温柔的解决方案,虽然服务本身的不可用,但是能够保证正常响应数据。
回到目录…
熔断机制是应对雪崩效应的一种微服务链路保护机制,当检测出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回”错误”的响应信息。当检测到该节点微服务响应正常后恢复调用链路。
实际上,熔断就是在降级的基础上进一步升级形成的,也就是说,在一段时间内多次调用失败,那么就直接升级为熔断。
我们可以在控制台打印两条日志,观察降级和熔断现象:
@Slf4j
@RestController
public class BorrowController {@Resourceprivate BorrowService borrowService;@HystrixCommand(fallbackMethod = "onError")@GetMapping("/borrow/{uid}")public UserBorrowView findUserBorrows(@PathVariable("uid") int uid) {log.info("开始向其它服务器发送请求!");return borrowService.getBorrowViewByUid(uid);}public UserBorrowView onError(int uid) {log.warn("服务错误, 进入备选方案!");return new UserBorrowView(null, Collections.emptyList());}
}
①服务降级:我们在浏览器中多次点击刷新按钮,对服务发起请求,可以看到后台:
②服务熔断:我们接着疯狂的刷新,继续不断地发起请求:
一开始的时候,会正常地去调用 Controller 对应的方法 findUserBorrows(),发现失败然后进入备选方法,但是我们发现在持续请求一段时间之后,没有再调用这个方法,而是直接调用备选方案,这便是升级到了熔断状态。
③再次检测:可以看到过了一段时间之后,会尝试正常执行一次 findUserBorrows()
,但是依然是失败状态,所以继续保持熔断状态。
④开启 UserService 服务器:当另外两个服务正常运行之后,当再次尝试调用 findUserBorrows()
之后会成功,于是熔断机制就关闭了,服务恢复运行。
总结一下:
它能够对一段时间内出现的错误进行侦测,当侦测到出错次数过多时,熔断器会打开,所有的请求会直接响应失败,一段时间后,只执行一定数量的请求,如果还是出现错误,那么则继续保持打开状态,否则说明服务恢复正常运行,关闭熔断器。
回到目录…
Feign 的降级也是依靠 Hystrix 组件实现的,所以我们的启动类依然需要用 @EnableHystrix
注解来修饰。
Hystrix 降级: 当用户服务挂掉后,我们的 Controller 中的方法在执行过程中会抛出异常,进而被 Hystrix 监控到并进行服务降级。
Feign 降级: 实际上导致方法执行异常的根源就是远程调用失败。所以我们直接给失败的远程调用添加一个替代方案,对其单独降级操作。
①我们知道 Feign 都是以接口的形式来声明远程调用,那么既然远程调用已经失效,我们就自行对其进行实现,创建一个实现类:BookFallbackClient
@Component //注意,需要将其注册为 Bean,Feign才能自动注入
public class BookFallbackClient implements BookClient {@Overridepublic Book findBookById(int bid) {return new Book();}
}
②实现完成后,我们只需要在原有的 BookClient 接口中指定失败替代实现即可:
@FeignClient(value = "bookservice", fallback = BookFallbackClient.class)
public interface BookClient {@GetMapping("/book/{bid}")Book findBookById(@PathVariable("bid") int bid);
}
③现在去掉 BorrowController 的@HystrixCommand
注解和备选方法:
@RestController
public class BorrowController {@Resourceprivate BorrowService borrowService;// @HystrixCommand(fallbackMethod = "onError")@GetMapping("/borrow/{uid}")public UserBorrowView findUserBorrows(@PathVariable("uid") int uid) {return borrowService.getBorrowViewByUid(uid);}
}
④最后我们在配置文件中开启熔断支持:
feign:circuitbreaker:enabled: true
现在启动服务,调用接口试试看:
可以看到,现在已经采用我们的替代方案作为结果。
Feign 服务降级也是可以升级为服务熔断的,下面我们会部署监控页面,就可以看到熔断的现象了。
回到目录…
①除了对服务的降级和熔断处理,我们也可以对其进行实时监控,只需要安装监控页面即可,这里我们创建一个新的项目 hystrix-dashboard,并导入依赖:
org.springframework.cloud spring-cloud-starter-netflix-hystrix-dashboard 2.2.10.RELEASE
②接着创建主类,注意需要添加@EnableHystrixDashboard
注解开启管理页面:
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashBoardApplication {public static void main(String[] args) {SpringApplication.run(HystrixDashBoardApplication.class, args);}
}
③接着给 hystrix 模块添加配置文件:
server:port: 8900
hystrix:dashboard:# 将localhost添加到白名单,默认是不允许的proxy-stream-allow-list: "localhost"
④然后我们将需要进行监控的 borrowservice 服务添加 Actuator
依赖:
org.springframework.boot spring-boot-starter-actuator
Actuator 是 SpringBoot 程序的监控系统,可以实现健康检查,记录信息等。在使用之前需要引入spring-boot-starter-actuator,并做简单的配置即可。
添加此依赖后,我们可以在 IDEA 中查看运行情况:
⑤然后在 borrowservice 服务的配置文件中配置 Actuator 添加暴露
:
management:endpoints:web:exposure:include: '*'
回到目录…
接着我们打开刚刚启动的管理页面,地址为:http://localhost:8900/hystrix/
在中间填写要监控的服务:比如借阅服务 http://localhost:8082/actuator/hystrix.stream,注意后面要添加/actuator/hystrix.stream
,然后点击 Monitor Stream 即可进入。
①我们可以看到监控页面的初始画面:
可以看到现在是 Loading 状态,这是因为还没有开始统计,我们现在尝试调用几次我们的服务:
②可以看到在调用之后,监控页面出现了信息:可以看到6次访问都是正常的,所以显示为绿色。
③接着我们将图书服务关闭,当错误率飙升到100%,且一段时间内持续出现错误,中心的圆圈也变成了红色,此时就是服务降级状态。
④在出现大量错误的情况下保持持续访问,可以看到此时已经将服务熔断,Circuit 更改为 Open 状态,并且图中的圆圈也变得更大,表示压力在持续上升。
回到目录…
总结:
提示:这里对文章进行总结:
本文是对SpringCloud的学习,学习了 Hystrix 的服务降级和熔断,Feign实现服务降级的方法,以及使用hystrix-dashboard 进行服务监控。之后的学习内容将持续更新!!!