一、Hystrix简介
在微服务架构中经常包括多个服务层,比如A为B提供服务,B为C和D提供服务,如果A出故障了就会导致B也不可用,最终导致C和D也不可用,这就形成了雪崩效应。
所以为了应对这种情况,我们就需要一种容错机制,该机制需要实行以下两点:
- 为网络请求设置超时,以便尽快释放资源
- 使用断路器模式,就像家里的电闸一样,如果电流过大就会立刻跳闸以保护电路防止发生火灾。当请求失败率达到一定的阈值,断路器就会打开,不会再请求依赖的服务。
Hystrix就是这样设计的,以实现容错处理,文章代码都可以在我的github下载。
二、通用方式整合Hystrix
- 复制项目microservice-consumer-movie-ribbon改为microservice-consumer-movie-ribbon-hystrix
- 添加所需依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
- 在启动类添加注解 @EnableHystrix 或者 @EnableCircuitBreaker以启用
- 修改MovieController代码,让findById方法具备容错能力
@RestController
public class MovieController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
private static final Logger logger = LoggerFactory.getLogger(MovieController.class);
@HystrixCommand(fallbackMethod = "findByIdFallBack")
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id){
//microservice-provider-user是虚拟主机名,默认和服务名称一致
//不能包括"_"之类的字符,否则Ribbon在调用时会报异常
return this.restTemplate.getForObject("http://microservice-provider-user/"+id,User.class);
}
public User findByIdFallBack(Long id){
User user = new User();
user.setId(-1L);
user.setAge(0);
user.setBalance(BigDecimal.ZERO);
user.setName("默认用户");
user.setUsername("默认用户");
return user;
}
}
这里考虑篇幅就不细说 @HystrixCommand注解的属性配置问题了。
测试
1.分别启动服务microservice-discovery-eureka,microservice-provider-user,microservice-consumer-movie-ribbon-hystrix
2.游览器访问http://localhost:8010/user/1获得如下结果
{"id":1,"username":"xxx","name":"zhangsan","age":22,"balance":100}
3.关掉服务microservice-provider-user再重新请求,获得如下结果。
{"id":-1,"username":"默认用户","name":"默认用户","age":0,"balance":0}
说明服务不可用时,进入到了回退方法。
为服务引入SpringBoot Actuator,再访问/health端点可以查看断路器状态,不过我尝试失败了。
三、Feign使用Hystrix
3.1为Feign添加回退
1.复制项目microservice-consumer-movie-feign改为microservice-consumer-movie-feign-hystrix-fallback,注意pom文件spring-cloud-starter-eureka 和 spring-cloud-starter-feign 已经过时。
2.Feign默认已经整合了Hystrix,所以不需要额外引入依赖。
3.将之前的UserFeignClient接口修改为如下
- /**
- * @author ship
- * @Description Feign的fallback测试
- * 使用@FeignClient的fallback属性指定回退类
- * @Date: 2018-07-17 13:25
- */
- "microservice-provider-user",fallback = FeignClientFallback.class) (name =
- public interface UserFeignClient {
- "/{id}",method = RequestMethod.GET) (value =
- User findById(@PathVariable("id") Long id);
- }
- /**
- * 回退类FeignClientFallback需实现Feign Client接口
- */
- class FeignClientFallback implements UserFeignClient {
- public User findById(Long id) {
- User user = new User();
- user.setId(-1L);
- user.setUsername("默认用户");
- return user;
- }
- }
开始测试
1.按顺序启动服务microservice-discovery-eureka,microservice-provider-user,microservice-consumer-movie-feign-hystrix-fallback
2.访问http://localhost:8010/user/1可获得正常结果
3.停止microservice-provider-user后再次访问获得如下结果说明已经成功了。
{"id":-1,"username":"默认用户","name":"默认用户","age":0,"balance":0}
如果你遇到了404问题,可能是因为从Spring Cloud Dalston开始,Feign默认是不开启Hystrix的。所以需要在application.yml文件上添加如下内容。
注意单词不要拼写错,我就是因为enabled写成了enable折腾了半天。。。。
3.2通过fallback factory检查回退原因
1.复制项目microservice-consumer-movie-feign改为microservice-consumer-movie-feign-hystrix-fallback-factory
2.修改UserFeignClient接口
- /**
- * @author ship
- * @Description Feign的fallback测试
- * 使用@FeignClient的fallback属性指定回退类
- * @Date: 2018-07-17 13:25
- */
- "microservice-provider-user",fallbackFactory = FeignClientFallbackFactory.class) (name =
- public interface UserFeignClient {
- "/{id}",method = RequestMethod.GET) (value =
- User findById(@PathVariable("id") Long id);
- }
- /**
- * 通过FallbackFactory检查回退原因
- */
- class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient>{
- private static final Logger logger = LoggerFactory.getLogger(FeignClientFallbackFactory.class);
- /**
- * 还可以根据不同的异常类型返回不同的结果
- * @param cause
- * @return
- */
- public UserFeignClient create(Throwable cause) {
- return new UserFeignClient() {
- public User findById(Long id) {
- //日志最好放在各个fallback方法中,而不是create方法中
- //否则在引用启动时,就会打印该日志
- logger.info("fallback reason was:",cause);
- User user = new User();
- user.setId(-1L);
- user.setUsername("默认用户");
- return user;
- }
- };
- }
- }
还可以根据不同的异常类型,返回不同的结果。
测试过程跟上面差不多,多了个查看日志的过程,在此省略。
四、Hystrix的监控
Hystrix提供了实时的监控,比如每秒执行的请求数,成功数等,这些对于查看服务的状态都很有意义。
使用Hystrix的hystrix-metrics-event-stream(spring-cloud-starter-hystrix已经包括)模块后,再添加spring-boot-starter-actuator就可以使用/hystrix.stream端点获得监控信息了。
之前的项目microservice-consumer-movie-ribbon-hystrix已经具备监控的能力,做个小测试。
1.依次启动microservice-discovery-eureka,microservice-provider-user,microservice-consumer-movie-ribbon-hystrix
2.访问http://localhost:8010/hystrix.stream,可以看到游览器一直处于请求状态且窗口空白,这是因为我们没有请求@HystrixCommand标注的方法,还没有数据产生。
3.先访问http://localhost:8010/user/1后再次访问http://localhost:8010/hystrix.stream,则可看到如下结果。
Feign项目的监控
1.复制项目microservice-consumer-movie-feign-hystrix-fallback修改为microservice-consumer-movie-feign-hystrix-fallback-stream
2.添加spring-cloud-starter-hystrix依赖,确保存在actuator的包。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
3.在启动类上添加注解@EnableCircuitBreaker就可以了。
五、使用Hystrix Dashboard数据可视化
可以使用Hystrix Dashboard,让监控数据可视化,图形化。
1.创建一个springboot项目,artifactId为microservice-hystrix-dashboard,并添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
2.启动类添加 @EnableHystrixDashboard注解
3.设置端口号为8030这样就可以了
4.访问http://localhost:8030/hystrix,即可看到主页,如图。
5.先进行之前的测试产生数据,再在URL输入http://localhost:8010/hystrix.stream并随便设置一个Title,点击最下方的按钮后即可看到。
六、使用Turbine聚合监控数据
6.1turbine简介
一般每个微服务都会部署多个实例,Hystrix Dashboard每次只能查看单个的很不方便,turbine是一个聚合Hystrix监控数据的工具,
它可以将所有 /hystrix.stream端点的数据聚合到一个组合的 /turbine.stream中,从而让集群的监控更加方便。
6.2编写turbine项目
6.3测试
1.启动项目microservice-discovery-eureka
2.启动项目microservice-provider-user
3.启动项目microservice-consumer-movie-ribbon-hystrix
4.启动项目microservice-consumer-movie-feign-hystrix-fallback-stream
5.启动项目microservice-hystrix-turbine
6.启动项目microservice-hystrix-dashboard
7.访问http://localhost:8010/user/1,让microservice-consumer-movie-ribbon-hystrix服务产生监控数据
8.访问http://localhost:8020/user/1,让microservice-consumer-movie-feign-hystrix-fallback-stream服务产生监控数据
9.打开dashboard首页,在URL一栏输入http://localhost:8031/turbine.stream,随意指定一个title,再点击monitor stream按钮后即可看到多个服务的监控数据。
总结
其实Hystrix还有很多地方没有讲,比如@HystrixCommand的属性配置问题,Hystrix的线程隔离策略和传播上下文等,第一次用markdown编辑器感觉还不错。