SpringCloud Netflix Hystrix
容错
在一个分布式系统里,一个服务往往要调用多个服务,可能存在某个服务调用失败, 比如超时、异常等,
要使用容错框架保证在某些服务调用出问题时,不会拖垮整个调用链路,系统依然可用。
Hystrix
Hystrix是一个容错框架,提供了隔离、熔断、服务降级、监控、cache等功能,可以有效防止被调服务故障造成的级联故障。
和eureka、ribbon、feign一样,hystrix也是Netflix旗下的项目,都被SpringCloud集成了。
服务限流
当此消费者对某提供者请求个数较多时,消费者可以限制自身对提供者发起的请求个数,请求个数超过指定的值时,使请求快速失败。
Hystrix的限流方式有2种:线程池、信号量。
服务监控
监控请求的失败率(一定时间内,请求失败个数)达到阈值,就打开断路器,熔断链路,使后续的请求快速失败。
熔断
熔断服务,包含被调用者、链路的下游服务,防止下游服务的故障影响到上游服务。
服务降级
服务调用失败默认会返回一堆英文的错误信息给用户,很不友好。
服务降级是在服务调用失败时自动执行预案,预案使用相同参数表、返回值类型,是备胎、次选,
预案可以只保留核心业务、抛弃不重要的业务,比如电商网站qps很大时,用户查询商品信息这一操作,标准业务是获取商品信息+评论+相似商品(商品推荐),预案只保留查询商品信息这一核心业务,去掉获取评论、推荐商品等非核心业务。
预案也可以连核心业务都不要,直接给出“太挤了,请稍后重试”之类的友好提示。
熔断和降级的异同点
相同点:从可用性和可靠性触发,防止系统崩溃,某些功能暂时不可用
不同点:服务熔断一般是下游服务故障导致的,而服务降级一般是从服务负载考虑,由调用方控制
自我修复
自我修复其实就是断路器状态的切换,断路器打开(熔断)后5min内的请求都快速失败;5min后断路器半开,放行部分请求,
如果这些请求(服务调用)都成功了,说明问题已修复,关闭断路器,链路恢复通行;否则继续下一个5min。
5min是窗口期,数值可以调。
使用Hystrix
Hystrix是在消费者(调用方)中使用的,一般要和Feign搭配使用
(1)在创建消费者时勾选Spring Cloud Circuit Breaker -> Hystrix [Maintenance]
也可以手动加hystrix的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
(2)引导类上加 @EnableCircuitBreaker或@EnableHystrix
@EnableHystrix中包含了@EnableCircuitBreaker这个注解
(3)在controller中设置回退方法
@Controller
@RequestMapping("/api/v1/user")
public class UserController {
@Resource
// private RestTemplate restTemplate;
private OrderFeignService orderFeignService; @RequestMapping("order/{user_id}")
@ResponseBody
@HystrixCommand(fallbackMethod = "findOrdersByUserIdFail") //指定回退方法
public Map<String,Object> findOrdersByUserId(@PathVariable("user_id") Integer userId){
//调用服务
// List<Order> orders = restTemplate.getForObject("http://order-service/api/v1/order/list/" + userId, List.class);
List<Order> orders = orderFeignService.findOrdersByUserId(userId); HashMap<String, Object> map = new HashMap<>();
map.put("code", 0);
map.put("data", orders); return map;
} /**
* 回退方法,回退方法命名一般是原方法名+Fail
*/
public Map<String,Object> findOrdersByUserIdFail(Integer userId){
//参数:远程服务接口,返回值类型(目标类型)
HashMap<String, Object> map = new HashMap<>();
map.put("code", -1);
map.put("msg", "人太多了,你被挤出来了,请稍后重试");
return map;
} }
Hystrix一般是在controller中设置的,也可以在其它地方进行设置。但服务调用要写在service层、然后在controller中调用service层,我这里图方便直接在controller中调用服务。
使用Feign、RestTemplate调用服务都可以。
返回的时候一般用map装载数据,code表示处理情况,前端或上游服务根据码值确定处理的情况,进行对应的数据展示。
比如code=xx表示处理成功了,如果是数据查询,用表格还是什么把获取的数据展示出来;如果code=xx表示处理失败,用提示框告诉用户失败了。
当然回退方法可以直接返回null,如果返回null,前端、上游服务处理返回结果时需要先判断返回的数据是否为null。
@HystrixCommand(fallbackMethod = "findOrdersByUserIdFail")标注在某个方法上,只对该方法有效;
@DefaultProperties(defaultFallback = "findOrdersByUserIdFail")标注在类上,对类中所有的方法都有效,该类中的某个方法执行失败时,都会调用默认的回退方法来代替。
使用Feign自带的Hystrix
上面的方式使用的是单独的Hystrix,也可以使用Feign内置的Hystrix。
同样是在消费中使用的,创建消费者时不需要勾选Hystrix,不需要添加Hystrix的依赖,因为Feign的依赖中已经包含了Hystrix。
在引导类中不需要使用Hystrix的注解
@EnableFeignClients
// @EnableHystrix
// 或者@EnableCircuitBreaker
(1)在配置文件中开启feign自带的hystrix
feign:
hystrix:
enabled: true
默认是false,需要手动开启
(2)写一个类实现Feign接口,和Feign接口放在同一个包下
@Component //放到spring容器中
public class OrderFeignServiceFallback implements OrderFeignService { //实现的方法就是接口中对应方法的回退方法
@Override
public List<Order> findOrdersByUserId(Integer user_id) {
return null;
} }
(3)在Feign接口中指定对应的回退类
@FeignClient(name = "order-service", fallback = OrderFeignServiceFallback.class)
public interface OrderFeignService { @GetMapping("/api/v1/order/list")
List<Order> findOrdersByUserId(@RequestHeader("user_id") Integer user_id); }
使用时不需要使用 @HystrixCommand 指定回退方法,调用失败时会自动执行回退类中对应的回退方法。
2种方式的比较
- 作用范围
第一种在哪里使用都行,可以给controller、service、dao或者其他地方的方法指定回退方法,哪个方法都可以加回退方法;
第二种只是给服务调用加回退方法,只作用于服务调用的语句。
- 服务调用方式
第一种可以使用RestTemplate或者Feign,第二种只能使用Feign。
总之第二种的使用范围很有限,只能对Feign方式的服务调用起到容错保护;
第一种的使用范围十分广泛,不局限于服务调用,可对整个应用起到容错保护,功能更加强大。
报警通知
1、通知用户
有些服务需要一段时候后才会处理,比如订单处理,会先放到消息队列中,逐个处理,
如果处理失败(服务调用失败)需要及时通知用户,比xx分钟内到账、xx分钟内出票,如果服务调用失败,在回退方法中要通知用户。
如果是车票、电影票、充话费之类较为重要的,要在回退方法中记录日志,并调用短信接口及时告知用户出票失败、充值失败,退款预计xx小时内到账。
通知时,如果当前线程还要做一些操作,比如返回数据给上游服务,通知是一个单独的业务,可以新建一个线程来通知,不要阻塞当前线程。
2、通知系统管理员、运维
统计服务调用失败的次数,如果指定时间内服务调用失败次数达到指定值,或者指定时间内服务调用失败的比例达到指定值,就以短信或者email的方式通知运维、管理员。
可以写一个工具类,用一个静态变量记录服务调用总数,调用某服务一次就+1,再使用一个静态变量统计该服务调用失败的次数;
写一个springboot定时任务,比如每5min执行一次,检测调用总次数、服务调用失败比例,达到指定值就通知管理员、运维,
检测调用总次数是为了确认被调者是否可能出问题了,不能调用总数1、失败率100%就通知管理员,可能是用户自己的问题。
通知之后或者比例未达到指定值,将统计值清空,重新统计下一个5min。
需要做好日志记录,方便管理员找出问题。
比如说被调用的服务集群挂了,不能每隔5min就通知管理一次,人家都开始处理了,你还一直通知。
可以在管理面板中提供按钮,点击可以关闭、开启通知管理员的功能,管理员收到故障通知后在面板中关闭通知管理员的功能,开始排查问题,解决后再开启通知管理员的功能。
也可以通知管理员之前先检测redis上有没有某个键值对,有就说明通知过了,不再通知;没有就设置此键值对,并指定过期时间,再通知管理员。比如过期时间设置为2h,2h通知一次。
Hystrix参数设置
Hystrix的参数配置可以写在@HystrixCommand(标注在方法上,只对该方法有效)、@DefaultProperties(标注在类上,对类中所有的方法都有效)注解中,
但配置自然是写在配置文件中好些,官方也是写在配置文件中的。
Hystrix的配置是写在消费者中的,常用配置如下:
hystrix:
command:
default:
execution:
#是否启用超时,默认true,一般都是设置为true
#timeout:
#enabled: true
isolation:
#有2种隔离策略:THREAD 线程池(默认)、SEMAPHORE 信号量
strategy: THREAD
thread:
#超时时间,默认1000,ms
timeoutInMilliseconds: 4000
#semaphore:
#设置信号量最大值,默认10
#maxConcurrentRequests: 100
上面使用的是hystrix,参数前缀是hystrix ;如果使用feign自带的hystrix,参数前缀是 feign: hystrix
超时时间指的是@HystrixCommand标注的方法执行的时间,如果使用的是Feign自带的Hystrix,指定的是服务调用的时间。
超时自动返回失败,如果将超时时间关闭,则一直等待服务调用完成,不会超时。一般都开启超时时间。
隔离策略即服务限流,消费者一般都会对提供者发起多个服务调用请求,消费者可以设置服务限流,限制本身对提供者的并发请求数。有2种策略
(1)THREAD 线程池,也叫做线程隔离,默认的隔离策略
为每个被调用的服务都创建一个线程池,将每个服务调用请求都包装为一个线程,放到线程池中。
线程池中的服务调用请求都是正在执行的,若线程池满了,放在队列中排队等待,若队列也满了,则后续对该被调者的请求直接快速失败。
Hystrix使用的是jdk自带的线程池,不是tomcat的线程池。并发执行的服务调用数取决于线程池能容纳的线程数。
(2)SEMAPHORE 信号量
信号量即可同时处理的请求个数,默认值10。
调用一次该服务,将信号量-1,一个调用请求结束将信号量+1,信号量为0时不再接受对该服务的调用请求,直接快速失败。
信号量适用于高并发服务调用,比如每秒数千次服务调用,因为使用线程池会导致线程池中同时存在几千个线程,开销巨大。
不用将服务调用请求包装为单独的线程,速度更快,但信号量一般只用于非网络调用。
快速失败是指不调用服务提供者,直接服务降级,执行回退方法。
如果要设置Hystrix的更多参数:
github上搜hystrix找到官方 -> WiKi -> 点击右侧的目录中的Configuration即可查看hystrix全部参数的介绍
直达车 https://github.com/Netflix/Hystrix/wiki/Configuration
SpringCloud Netflix Hystrix的更多相关文章
- SpringCloud学习笔记(五、SpringCloud Netflix Hystrix)
目录: Hystrix简介 线程隔离:线程池.信号量 服务降级.服务熔断.请求缓存.请求合并 Hystrix完整流程.Hystrix属性值 注解方式实现Hystrix Hystrix Dashboar ...
- Spring Cloud 系列之 Netflix Hystrix 服务容错
什么是 Hystrix Hystrix 源自 Netflix 团队于 2011 年开始研发.2012年 Hystrix 不断发展和成熟,Netflix 内部的许多团队都采用了它.如今,每天在 Netf ...
- Spring Cloud 系列之 Netflix Hystrix 服务监控
Actuator Hystrix 除了可以实现服务容错之外,还提供了近乎实时的监控功能,将服务执行结果和运行指标,请求数量成功数量等等这些状态通过 Actuator 进行收集,然后访问 /actuat ...
- springCloud学习3(Netflix Hystrix弹性客户端)
springcloud 总集:https://www.tapme.top/blog/detail/2019-02-28-11-33 本次用到全部代码见文章最下方. 一.为什么要有客户端弹性模式 所 ...
- SpringCloud Netflix (五) : Hystrix 服务熔断和服务降级
什么是Hystrix 在分布式环境中,许多服务依赖项中的一些服务依赖不可避免地会失败.Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助您控制这些分布式服务之间的交互.Hystrix通过隔离服务 ...
- SpringCloud系列之服务容错保护Netflix Hystrix
1. 什么是雪崩效应? 微服务环境,各服务之间是经常相互依赖的,如果某个不可用,很容易引起连锁效应,造成整个系统的不可用,这种现象称为服务雪崩效应. 如图,引用国外网站的图例:https://www. ...
- springcloud学习04- 断路器Spring Cloud Netflix Hystrix
依赖上个博客:https://www.cnblogs.com/wang-liang-blogs/p/12072423.html 1.断路器存在的原因 引用博客 https://blog.csdn.ne ...
- Spring-cloud (九) Hystrix请求合并的使用
前言: 承接上一篇文章,两文本来可以一起写的,但是发现RestTemplate使用普通的调用返回包装类型会出现一些问题,也正是这个问题,两文没有合成一文,本文篇幅不会太长,会说一下使用和适应的场景. ...
- java框架之SpringCloud(5)-Hystrix服务熔断、降级与监控
前言 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败.不做任何处理的情况下,很容易导致服务雪崩. 服务雪崩:多个微服务之间调用的时候,假设 ...
随机推荐
- Java【第一课 java基本结构】
一.java基本结构 上面是java的基本组成,包括外层的框架.java入口程序框架 二.java的第一个程序 首先创建一个文件,名字叫做helloworld.java,后缀名为java public ...
- spring boot中通用应用程序属性
可以在application.properties文件内部application.yml,文件内部或命令行开关中指定各种属性.本附录提供了常见的Spring Boot属性列表以及对使用它们的基础类的引 ...
- Certificate Request Processor: Invalid provider specified. 0x80090013 (-2146893805 NTE_BAD_PROVIDER)
通过INF文件创建CSR时遇到Certificate Request Processor: Invalid provider specified. 0x80090013 (-2146893805 NT ...
- Win10桌面菜单弹出cmd解决办法
现象 Win10右键菜单打开弹出命令提示符 原有个性化.显示设置.网络和Internet设置无法使用 解决 注册表定位到HKEY_CURRENT_USER\Software\Classes\ ms-s ...
- Hadoop学习之路(7)MapReduce自定义排序
本文测试文本: tom 20 8000 nancy 22 8000 ketty 22 9000 stone 19 10000 green 19 11000 white 39 29000 socrate ...
- Java(四)输出和输入函数
介绍一下Java里简单常用的输入输出方法. Java的输出函数很简单,直接调用System类的out对象的print函数即可. 代码: System.out.print(a);//输出变量a的值 Sy ...
- .net mvc 多文件上传
1.input文件上传设置允许选择多个文件,设置属性 multiple即可 <input type="file" multiple="multiple" ...
- 08-SV面向对象编程的高级技巧指南
1.原始类与扩展类 (1)原始类被称为父类或者超类,扩展类被称为派生类或者子类.扩展类可以直接访问原始类和其本身的所有变量,应该将原始类中的子程序定义成虚拟的,这样它们就可以在扩展类中重定义.new函 ...
- a++ 和 ++a
//a++ 先赋值,后加 var a = 1 console.log(a++);//1 console.log(a) //2 //++a 先赋值,后加 var a = 1 console.log(++ ...
- H5_0018:z-index失效的原因
在做的过程中,发现了一个很简单却又很多人应该碰到的问题,设置Z-INDEX属性无效. 在CSS中,只能通过代码改变层级,这个属性就是z-index, 要让z-index起作用有个小小前提,就是元素的p ...