一、前言
1、为什么需要断路器
在分布式架构中,一个应用依赖多个服务是非常常见的,如果其中一个依赖由于延迟过高发生阻塞,调用该依赖服务的线程就会阻塞,如果相关业务的QPS较高,就可能产生大量阻塞,从而导致该应用/服务由于服务器资源被耗尽而拖垮。
另外,故障也会在应用之间传递,如果故障服务的上游依赖较多,可能会引起服务的雪崩效应。就跟数据瘫痪,会引起依赖该数据库的应用瘫痪是一样的道理。
所以,断路器就是用来支持服务隔离、熔断等操作的工具。断路器会以隔离的方式来处理服务请求,当断路数量达到阈值,就会触发熔断(直接返回失败)。
2、什么是Hystrix?
Hystrix是SOA/微服务架构中提供服务隔离、熔断、降级机制的工具/框架。通过以上手段来降低服务故障带来的关联影响,以提高系统的整体可用性。
Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable. -https://github.com/Netflix/Hystrix
Hystrix就是断路器的典型代表。
Hystrix工作原理:https://ken.io/note/netflix-hystrix-intro-principle
3、本篇环境信息
框架 | 版本 |
---|---|
Spring Boot | 2.0.0.RELEASE |
Spring Cloud | Finchley.BUILD-SNAPSHOT |
JDK | 1.8.x |
4、准备工作
- 准备Eureka Server、服务提供者
参考上一篇 https://ken.io/note/spring-cloud-feign-quickstart
源码:https://github.com/ken-io/springcloud-course/tree/master/chapter-03/
启动Eureka Server: http://localhost:8800
启动Test Service:http://localhost:8602
- 了解服务消费者
服务消费者Ribbon: https://ken.io/note/spring-cloud-ribbon-quickstart
服务消费者Feign:
https://ken.io/note/spring-cloud-feign-quickstart
二、Ribbon + Hystrix应用
本篇基于 https://ken.io/note/spring-cloud-ribbon-quickstart
中ribbonclient项目代码进行修改,引入Spring Cloud Netflix Hystrix
源码:https://github.com/ken-io/springcloud-course/tree/master/chapter-02/ribbonclient
1、项目中引入Hystrix
修改pom.xml,引入Spring Cloud Netflix Hystrix
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、配置Hystrix启动类
修改启动类App.java,增加@EnableHystrix注解开启Hystrix
@EnableHystrix
@EnableDiscoveryClient
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
3、断路处理实现
修改TestService.java,增加断路器功能
- 在index方法上增加注解
@HystrixCommand
并通过fallbackMethod参数指定断路后执行的方法 - 定义断路处理方法,返回服务/操作断路后的提示
@Service
public class TestService {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "indexError")
public Object index() {
return restTemplate.getForObject("http://testservice", String.class);
}
public Object plus(int numA, int numB) {
String url = String.format("http://testservice/plus?numA=%s&numB=%s", numA, numB);
return restTemplate.getForObject(url, String.class);
}
public Object indexError() {
return "{\"code\": 999,\"message\": \"服务断路\"}";
}
}
4、断路处理测试
启动 ribbonclient 项目,
访问:http://localhost:8604/ti ,将看到
{
"code": 0,
"message": "hello",
"content": null,
"serviceName": "testservice",
"host": "localhost:8602"
}
关闭testservice,然后再访问 http://localhost:8604/ti ,将看到
{
"code": 999,
"message": "服务断路"
}
这就说明,当testservice不可用的时候,我们访问增加了Hystrix容错措施的接口,会触发快速失败,立即执行fallback。而不是一直等待直到超时,很大程度上降低了造成阻塞可能。
三、Feign + Hystrix应用
本篇基于 https://ken.io/note/spring-cloud-feign-quickstart
中feignclient项目代码进行修改
源码:https://github.com/ken-io/springcloud-course/tree/master/chapter-03/feignclient
Feign已经引入了Hystrix,所以不需要再单独引入
1、开启Hystrix
修改application.yml,开启Hystrix
feign:
hystrix:
enabled: true
2、断路处理实现
- 新建 TestServiceHystrix.java
TestServiceHystrix会作为TestService的断路处理实现
package io.ken.springcloud.feignclient.service;
import io.ken.springcloud.feignclient.model.Plus;
import io.ken.springcloud.feignclient.model.Result;
import org.springframework.stereotype.Component;
@Component
public class TestServiceHystrix implements TestService {
@Override
public String indexService() {
return "{\"code\": 999,\"message\": \"服务断路\"}";
}
@Override
public Result plusService(int numA, int numB) {
Result result = new Result();
result.setCode(999);
result.setMessage("服务断路");
return new Result();
}
@Override
public Result plusabService(Plus plus) {
Result result = new Result();
result.setCode(999);
result.setMessage("服务断路");
return new Result();
}
@Override
public Result plus2Service(Plus plus) {
Result result = new Result();
result.setCode(999);
result.setMessage("服务断路");
return new Result();
}
}
- 修改TestService,指定fallback类
@FeignClient(value = "testservice", fallback = TestServiceHystrix.class)
public interface TestService {
@RequestMapping(value = "/", method = RequestMethod.GET)
String indexService();
@RequestMapping(value = "/plus", method = RequestMethod.GET)
Result plusService(@RequestParam(name = "numA") int numA, @RequestParam(name = "numB") int numB);
@RequestMapping(value = "/plus", method = RequestMethod.POST, consumes = "application/json")
Result plusabService(Plus plus);
@RequestMapping(value = "/plus2", method = RequestMethod.POST)
Result plus2Service(@RequestBody Plus plus);
}
3、断路处理测试
启动 feignclient 项目
访问:http://localhost:8605/ti ,将看到
{
"code": 0,
"message": "hello",
"content": null,
"serviceName": "testservice",
"host": "localhost:8602"
}
关闭testservice,然后再访问 http://localhost:8605/ti ,将看到
{
"code": 999,
"message": "服务断路"
}
这就说明,当testservice不可用的时候,我们访问增加了Hystrix容错措施的接口,会触发快速失败,立即执行fallback。而不是一直等待直到超时,很大程度上降低了造成阻塞可能。
四、备注
- 本篇代码示例
https://github.com/ken-io/springcloud-course/tree/master/chapter-04
- 本篇参考
https://github.com/Netflix/Hystrix/wiki
- 延伸阅读
https://ken.io/note/netflix-hystrix-intro-principle
http://tech.lede.com/2017/06/15/rd/server/hystrix/