『互联网架构』软件架构-实战Hystrix实战(96)
(一)Hystrix 介绍
- 官网
https://github.com/Netflix/Hystrix
- 学习直接看
https://github.com/Netflix/Hystrix/wiki
(二)Hystrix 降级,超时
- 引入Springcloud Hystrix依赖,
一定要记住谁调用在谁哪里做处理,而不是被调用方,被调用方服务都挂了,你写降级有什么用?
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
- Hystrix是怎么做到降级的
通过一种叫做“命令模式”的方式,继承(HystrixCommand类)来包裹具体的服务调用 逻辑(run方法), 并在命令模式中添加了服务调用失败后的降级逻辑(getFallback),见 (OrderServiceCommand类) 源码:06-ms-consumer-order-ribbon-hystrix-customizing 通过配置类的方式
用Hystrix的注解@HystrixCommand可以更简单的实现上面的降级逻辑 直接在接口调用方的方法上增加注解@HystrixCommand(fallbackMethod = "findByIdFallback") 注解的源码:06-ms-consumer-order-ribbon-hystrix-fallback
- 超时回退
在用户微服务工程里将UserController的findById接口增加执行等待时间,让该接口的执行时间变长,Hystrix调用接口默认两秒超时,超时后会自动执行降级方法。注解的源码:06-ms-provider-user
- 启动流程06的源码
provider-user,consumber-order,eureka-server 必须都需要启动
(三)Hystrix 熔断,限流
- 熔断怎么实现
源码:06-ms-consumer-order-ribbon-hystrix-fusing 06-ms-provider-user 里将UserController的findById接口增加模拟报错代码
测试报错和正常的情况,我们可以看到当报错达到一定阈值时,会自动熔断,阈值可以配置# 一个rolling window内最小的请求数。如果设为20,那么当一个rolling window的时间内(比如说1个rolling window是10秒)收到19个请求,即使19个请求都失败,也不会触发circuit break。默认20hystrix.command.default.circuitBreaker.requestVolumeThreshold# 触发短路的时间值,当该值设为5000时,则当触发circuit break后的5000毫秒内都会拒绝request,也就是5000毫秒后才会关闭circuit。默认5000hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds
(四)熔断器原理
熔断器模式定义了熔断器开关相互转换的逻辑
服务的健康状况 = 请求失败数 / 请求总数。熔断器开关由关闭到打开的状态转换是通过当前服务健康状况和设定阈值比较决定的.
- 当熔断器开关关闭时, 请求被允许通过熔断器. 如果当前健康状况高于设定阈值, 开关继续保持关闭. 如果当前健康状况低于设定阈值, 开关则切换为打开状态。
- 当熔断器开关打开时, 请求被禁止通过。
- 当熔断器开关处于打开状态, 经过一段时间后, 熔断器会自动进入半开状态, 这时熔断器只允许一个请求通过. 当该请求调用成功时, 熔断器恢复到关闭状态. 若该请求失败, 熔断器继续保持打开状态, 接下来的请求被禁止通过. 熔断器的开关能保证服务调用者在调用异常服务时, 快速返回结果, 避免大量的同步等待。并且熔断器能在一段时间后继续侦测请求执行结果, 提供恢复服务调用的可能。
(五)限流,线程资源隔离
源码:06-ms-consumer-order-ribbon-hystrix-threadisolation在用户微服务工程(06-ms-provider-user)里将UserController的findById接口模拟执行等待的代码。
在订单微服务工程(06-ms-consumer-order-ribbon-hystrix-thread-isolation)中修改接口超时配置为20秒。
用注解配置线程池大小
- CommandGroupKey:配置全局唯一标识服务分组的名称,比如,库存系统就是一个服务分组。当我们监控时,相同分组的服务会聚合在一起,必填选项。
- CommandKey:配置全局唯一标识服务的名称,比如,库存系统有一个获取库存服务,那么就可以为这个服务起一个名字来唯一识别该服务,如果不配置,则默认是简单类名。
- ThreadPoolKey:配置全局唯一标识线程池的名称,相同线程池名称的线程池是同一个,果不配置,则默认是分组名,此名字也是线程池中线程名字的前缀。
- ThreadPoolProperties:配置线程池参数,coreSize配置核心线程池大小和线程池最大大小,keepAliveTimeMinutes是线程池中空闲线程生存时间(如果不进行动态配置,那么是有任何作用的),maxQueueSize配置线程池队列最大大小,queueSizeRejectionThreshold限定当前队列大小,即实际队列大小由这个参数决定,通改变queueSizeRejectionThreshold可以实现动态队列大小调整。
- CommandProperties:配置该命令的一些参数,如executionIsolationStrategy配置执行离策略,默认是使用线程隔离,此处我们配置为THREAD,即线程池隔离。
此处可以粗粒度实现隔离,也可以细粒度实现隔离,如下所示。服务分组+线程池
粗粒度实现,一个服务分组/系统配置一个隔离线程池即可,不配置线 程池名称或者相同分组的线程池名称配置为一样。
服务分组+服务+线程池
细粒度实现,一个服务分组中的每一个服务配置一个隔离线程池,为不同的命令实现配置不同的线程池名称即可。
混合实现
一个服务分组配置一个隔离线程池,然后对重要服务单独设置隔离线程池。
(六)Hystrix服务调用的内部逻辑
- 构建Hystrix的Command对象, 调用执行方法。
- Hystrix检查当前服务的熔断器开关是否开启, 若开启, 则执行降级服务getFallback方法。
- 若熔断器开关关闭, 则Hystrix检查当前服务的线程池是否能接收新的请求, 若线程池已满, 则执行降级服务getFallback方法。
- 若线程池接受请求, 则Hystrix开始执行服务调用具体逻辑run方法。
- 若服务执行失败, 则执行降级服务getFallback方法, 并将执行结果上报Metrics更新服务健康状况。
- 若服务执行超时, 则执行降级服务getFallback方法, 并将执行结果上报Metrics更新服务健康状况。
- 若服务执行成功, 返回正常结果。
- 若服务降级方法getFallback执行成功, 则返回降级结果。
- 若服务降级方法getFallback执行失败, 则抛出异常。
- 从web图片裁剪出发:了解H5中的Blob
- Android子线程更新UI主线程方法之Handler
- Drawable.Bitmap.Canvas.Paint.Matrix
- 关于JSON.stringify和Unicode编码,需要注意的几点
- 用 PHP 的方式实现的各类算法合集
- Nginx 反向代理解决前后端联调跨域问题
- JavaScript对象length
- Go1.8.4和Go1.9.1版本发布
- Javascript数组操作
- Tensorflow官方语音识别入门教程 | 附Google新语音指令数据集
- jQuery VS JavaScript原生API
- 居于H5的多文件、大文件、多线程上传解决方案
- 抛弃websocket,前端直接打通信道,webRTC搭建音视频聊天
- Golang学习-第三篇 认识Web框架
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- xshell 远程登陆CentOS7 免密登陆的思路详解
- Linux服务器下Nginx与Apache共存的实现方法分析
- 浅析Linux中vsftpd服务配置(匿名,用户,虚拟用户)
- CentOS7开启MySQL8主从备份、每日定时全量备份(推荐)
- leetcode栈之用两个栈实现队列
- Ubuntu 18.04通过命令禁用/开启触控板
- 如何利用watch帮你重复执行命令
- Linux查看当前登录用户并踢出用户的命令
- centos7下安装java及环境变量配置技巧
- Ubuntu系统下扩展LVM根目录的方法
- 将宝塔面板linux版装在/www以外的目录的方法
- 详解在Linux下9个有用的touch命令示例
- 一步步教你如何开启、关闭ubuntu防火墙
- Linux环境ActiveMQ部署方法详解
- Ubuntu 16.04无法切换root权限问题的解决