SpringCloud系列十五:使用Hystrix实现容错
1. 回顾
上文讲解了容错的重要性,以及容错需要实现的功能。
本文来讲解使用Hystrix实现容错。
2. Hystrix简介
Hystrix是Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或第三方库,防止级联失败,从而提高系统的可用性与容错性。
Hystrix主要通过以下几点实现延迟和容错:
- 包裹请求:使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中执行。
这使用到了设计模式中的“命令模式”。
- 跳闸机制:当某服务的错误率超过一定阈值时,Hystrix可以自动或者手动跳闸,停止请求该服务一段时间。
- 资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就被立即拒绝,
而不是排队等候,从而加速失败判定。
- 监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等。
- 回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。
- 自我修复:断路器打开一段时间后,会自动进入“半开”状态。断路器打开、关闭、半开的逻辑转换,上文已经详细探讨过,不再赘述。
3. 通用方式整合Hystrix
> 复制项目 microservice-consumer-movie-ribbon,将 ArtifactId 修改为 microservice-consumer-movie-ribbon-hystrix
> 添加 hystrix 的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
> 在启动类上添加 @EnableCircuitBreaker 或 @EnableHystrix 注解,从而为项目启用断路器支持
package com.itmuch.cloud.microserviceconsumermovieribbonhystrix; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate; @SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
public class MicroserviceConsumerMovieRibbonHystrixApplication { public static void main(String[] args) {
SpringApplication.run(MicroserviceConsumerMovieRibbonHystrixApplication.class, args);
} @Bean
@LoadBalanced // 实现负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
> 修改 MovieController,让其中的findById方法具备容错能力。
package com.itmuch.cloud.microserviceconsumermovieribbonhystrix.controller; import com.itmuch.cloud.microserviceconsumermovieribbonhystrix.pojo.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; @RestController
public class MovieController { private static final Logger LOGGER = LoggerFactory.getLogger(MovieController.class); @Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient; @HystrixCommand(fallbackMethod = "findByIdFallback")
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
return this.restTemplate.getForObject("http://microservice-provider-user/" + id, User.class);
} @GetMapping("/log-instance")
public void logUserInstance() {
ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");
// 打印当前选择的是哪个节点
MovieController.LOGGER.info("{}:{}:{}", serviceInstance.getServiceId(), serviceInstance.getHost(),
serviceInstance.getPort());
} public User findByIdFallback(Long id) {
LOGGER.warn("请求异常,执行回退方式");
User user = new User();
user.setId(-1L);
user.setName("默认用户");
return user;
} }
> 启动项目 microservice-discovery-eureka
> 启动项目 microservice-provider-user
> 启动项目 microservice-consumer-movie-ribbon-hystrix
> 访问 http://localhost:8010/user/1,获得如下结果,说明可正常访问
> 停止项目 microservice-provider-user
> 访问 http://localhost:8010/user/1,获得如下结果,说明当用户微服务不可用时,进入了回退方法
注意:当请求失败、被拒绝、超时或者断路器打开时,都会进入回退方法。但进入回退方法并不意味着断路器已被打开。
4. Hystrix断路器的状态监控与深入理解
还记得之前已经为项目引入了Spring Boot Actuator 的依赖,该依赖的作用就是监控应用程序的运行状态。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
断路器的状态也会暴露在Actuator提供的 /actuator/health 端口中,这样就可以直观地了解断路器的状态。
但是之前使用的是 Actuator 的默认配置。在默认配置中,/actuator/health 端口只能查看系统的状态,不能查看详细信息,
因此需要对 Actuator进行进一步配置。
在 application.yml 中添加如下配置
management:
endpoint:
health:
show-details: always
> 启动项目 microservice-discovery-eureka
> 启动项目 microservice-consumer-movie-ribbon-hystrix
> 访问 http://localhost:8010/user/1,结果如下,说明已执行了回退逻辑,返回了默认用户。
> 访问 http://localhost:8010/actuator/health,结果如下,此时Hystrix的状态依然是 UP,这是因为我们的失败率还没有达到阈值
(默认是5秒返回20次失败)
> 持续快速的访问 http://localhost:8010/user/1,然后访问 http://localhost:8010/actuator/health,此时结果如下
注意:由上面的测试可以发现——执行回退逻辑并不代表断路器已经打开。请求失败、超时、被拒绝以及断路器打开时都会执行回退逻辑。
5. Hystrix线程隔离策略与传播上下文
先来阅读一下Hystrix官方Wiki(https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.strategy)
执行
以下属性控制 HystrixCommand.run() 是如何运行的
execution.isolation.strategy
这个属性决定了 HystrixCommand.run() 以哪种隔离策略去执行,下面两种选择中的一个:
- THREAD(线程隔离):它将在单独的线程上执行,并发请求受线程池中的线程数量的限制。
- SEMAPHORE(信号量隔离):它将在调用线程上执行,开销相对较小,并发请求收到信号量个数的限制。
Thread or Semaphore
默认并且推荐的设置是,运行 HystrixCommand 使用线程隔离(THREAD)HystrixObservableCommand 使用信号量隔离(SEMAPHORE)
在线程中执行命令有一个除网络超时以外的额外保护层。
一般来说,只有当调用负载非常高时(每个实例每秒调用数百次)才需要对 HystrixCommand 使用信号量隔离,因为这种场景下
使用单独线程开销太高,这通常只适用于非网络调用。
了解了Hystrix的隔离策略后,再来看一下 Spring Cloud 官方的文档(http://cloud.spring.io/spring-cloud-static/Finchley.M8/single/spring-cloud.html#_propagating_the_security_context_or_using_spring_scopes)
如果你想传播线程本地的上下文到 @HystrixCommand,默认声明将不会工作,因为它会在线程池中执行命令(在超时的情况下)。
你可以使用一些配置,让 Hystrix 使用相同的线程,或者直接在注解中让 Hystrix 使用不同的隔离策略。例如:
@HystrixCommand(fallbackMethod = "stubMyService",
commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE")
}
)
...
这也适用于使用 @SessionScope 和 @RequestSession 的情况。你会知道什么时候需要这么做,因为会发生一个运行时异常,
说它找不到作用域上下文(scoped context)。
你还可以将 hystrix.shareSecurityContext 属性设置为 true,这样将会自动配置一个 Hystrix 并发策略插件的 hook,这个hook会
将 SecurityContext 从主线程传输到 Hystrix 的命令。因为 Hystrix 不允许注册多个 Hystrix 策略,所以可以声明 HystrixConcurrencyStrategy
为一个Spring bean来实现扩展。Spring Cloud会在Spring的上下文中查找你的实现,并将其包装在自己的插件中。
把Spring Cloud 和 Hystrix 的文档对照阅读,可以帮助理解相关概念。
- Hystrix的隔离策略有THREAD和SEMAPHORE两种,默认是THREAD。
- 正常情况下,保持默认即可。
- 如果发生找不到上下文的运行时异常,可考虑将隔离策略设置为SEMAPHORE。
6. 总结
本文讲解了Hystrix的整合,对Hystrix断路器的理解及监控,还有Hystrix的隔离策略与传播上下文等。
下文将讲解Feign使用Hystrix。敬请期待~~~
7. 参考
周立 --- 《Spring Cloud与Docker微服务架构与实战》
SpringCloud系列十五:使用Hystrix实现容错的更多相关文章
- SpringCloud系列十四:实现容错的手段
1. 回顾 前面已用Eureka实现了微服务的注册与发现,Ribbon实现了客户端侧的负载均衡,Feign实现了声明式的API调用. 2. 实现容错的手段 如果服务提供者响应非常慢,那么消费者对提供者 ...
- 跟我学SpringCloud | 第十五篇:微服务利剑之APM平台(一)Skywalking
目录 SpringCloud系列教程 | 第十五篇:微服务利剑之APM平台(一)Skywalking 1. Skywalking概述 2. Skywalking主要功能 3. Skywalking主要 ...
- 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- 聊聊MySQL的加锁规则《死磕MySQL系列 十五》
大家好,我是咔咔 不期速成,日拱一卒 本期来聊聊MySQL的加锁规则,知道这些规则后可以判断SQL语句的加锁范围,同时也可以写出更好的SQL语句,防止幻读问题的产生,在能力范围内最大程度的提升MySQ ...
- SpringCloud系列十六:Feign使用Hystrix
1. 回顾 上文讲解了使用注解@HystrixCommand的fallbackMethod属性实现回退.然而,Feign是以接口形式工作的, 它没有方法体,前文讲解的方式显然不适用与Feign. 事实 ...
- 【Qt编程】基于Qt的词典开发系列<十五>html特殊字符及正则表达式
1.html特殊字符的显示 我们知道html语言和C语言一样也有一些特殊字符,它们是不能正常显示的,必须经过转义,在网上可以查到如何显示这些字符,如下图所示: 上图给了最常用的特殊字符的显示,下面我们 ...
- SSE图像算法优化系列十五:YUV/XYZ和RGB空间相互转化的极速实现(此后老板不用再担心算法转到其他空间通道的耗时了)。
在颜色空间系列1: RGB和CIEXYZ颜色空间的转换及相关优化和颜色空间系列3: RGB和YUV颜色空间的转换及优化算法两篇文章中我们给出了两种不同的颜色空间的相互转换之间的快速算法的实现代码,但是 ...
- SpringCloud系列十二:SpringCloudSleuth(SpringCloudSleuth 简介、SpringCloudSleuth 基本配置、数据采集)
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringCloudSleuth 2.具体内容 Sleuth 是一种提供的跟踪服务,也就是说利用 sleuth 技术 ...
- SpringCloud系列十:SpringCloudConfig 高级配置(密钥加密处理(JCE)、KeyStore 加密处理、SpringCloudConfig 高可用机制、SpringCloudBus 服务总线)
1.概念:SpringCloudConfig 高级配置 2.具体内容 在 SpringCloudConfig 之中考虑到所有配置文件都暴露在远程仓库之中的安全性问题,所以提供有安全访问的处理机制,这样 ...
随机推荐
- dfs序学习总结
dfs序: 每个节点在dfs中的进出栈的时间序列. 树是非线性结构,根节点连着子节点,那么dfs序...节点进出栈的时间先后? 从根节点入栈,然后左儿子入栈,左儿子出栈,右儿子入栈,右儿子出栈,根节点 ...
- poj2778(AC 自动机)
poj2778 题意 构造只包含 \(A, T, C, G\) 的字符串,且满足不出现指定的一些字符串,问长度为 \(n\) 的字符串有多少种 ? 分析 AC 自动机 + 矩阵快速幂的神题 ,知识点很 ...
- 【Ubuntu】使用root账户登录ubuntu
由于经常使用,所以写个博客记下来以便后来查看. 1.修改root账户密码:sudo passwd root,输密码 2.修改/usr/share/lightdm/lightdm.conf.d/50-u ...
- 【博弈论】poj2484 A Funny Game
如果当前状态可以根据某条轴线把硬币分成两个相同的组,则当前状态是必败态. 因为不论在其中一组我们采取任何策略,对方都可以采取相同的策略,如此循环,对方必然抽走最后一枚硬币. 因为我们先手,因此抽完后盘 ...
- 【块状树】【LCA】bzoj1787 [Ahoi2008]Meet 紧急集合
分块LCA什么的,意外地快呢…… 就是对询问的3个点两两求LCA,若其中两组LCA相等,则答案为第三者. 然后用深度减一减什么的就求出距离了. #include<cstdio> #incl ...
- ajax变量作用域的问题
需求:使得一个变量在ajax内外都有作用域 方法:设置为同步请求 async:false
- 个人python学习路线记录
一.入门视频 零基础入门学习Python --小甲鱼 二.博客园 python快速教程 http://www.cnblogs.com/vamei/archive/2012/09/13/2682778. ...
- Ubuntu 16.04下将ISO镜像制作成U盘启动的工具-UNetbootin(UltraISO的替代工具)
说明: 1.在Windows下制作ISO镜像的U盘启动工具有很多,但是在Linux平台下估计就只有UNetbootin这个工具最好用了,效果和Windows下的制作方法差不多,但是这个工具只能针对Li ...
- 130804组队练习赛ZOJ校赛
A.Ribbon Gymnastics 题目要求四个点作圆,且圆与圆之间不能相交的半径之和的最大值.我当时想法很简单,只要两圆相切,它们的半径之和一定最大,但是要保证不能相交的话就只能取两两个点间距离 ...
- CLR探索系列:Windbg+SOS动态调试分析托管代码
http://blog.csdn.net/garyye/article/details/4788070 在使用VS进行托管应用程序的调试的时候,有的时候总感觉有些力不从心.譬如查看一个托管堆或者计 ...