Hystrix简介
属于一种容错机制 ,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。Hystrix主要通过以下几点实现延迟和容错
1、包裹请求:使用HystrixCommand包裹对依赖的调用逻辑。自动投递微服务方法(@HystrixCommand 添加Hystrix控制) ——调⽤简历微服务 
2、跳闸机制:当某服务的错误率超过⼀定的阈值时,Hystrix可以跳闸,停⽌请求 该服务⼀段时间。 
3、资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(舱壁模式)(或者信号量)。如果该线程池已满, 发往该依赖的请求就被立即拒绝,而不是排队等 待,从而加速失败判定。 
4、监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等
5、回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回 退逻辑由开发人员自行提供,例如返回一个缺省值。
6、我修复:断路器打开一段时间后,会自动进行“半开”状态。  
雪崩场景

扇入:代表着该微服务被调用的次数,扇入大,说明该模块复用性好
扇出:该微服务调用其他微服务的个数,扇出大,说明业务逻辑复杂
扇入大是一个好事,扇出大不一定是好事
最下游简历微服务响应时间过长,大量请求阻塞,大量线程不会释放,会导致服务器资源耗尽,最终导致上游服务甚至整个系统瘫痪。
雪崩效应解决方案
应对微服务中的雪崩效应,这三种手段都是从系统可用性、可靠性⻆度出发,尽量防止系统整体缓慢甚至瘫痪
服务熔断
当扇出链路的某个微服务不可用或者响应时间太长时,熔断该节点微服务的调用,进行服务的降级,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路。  
注意: 
1)服务熔断重点在“断”,切断对下游服务的调⽤ 
2)服务熔断和服务降级往往是一起使用的,Hystrix就是这样。  
服务降级
通俗讲就是整体资源不够用了,先将一些不关紧的服务停掉(调用到的时候,再给你返回一个预留的值,也叫做兜底数据),待渡过难关高峰过去,再把那些服务打开。 服务降级一般是从整体考虑,就是当某个服务熔断之后,服务器将不再被调用,此刻客户端可以自己准备一个本地的fallback回调,返回一个缺省值,这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强。
服务限流
服务降级是当服务出问题或者影响到核心流程的性能时,暂时将服务屏蔽掉,待高峰或者问题解决后再打开;但是有些场景并不能用服务降级来解决,比如秒杀业务 这样的核心功能,这个时候可以结合服务限流来限制这些场景的并发/请求量 限流措施也很多,比如  
限制总并发数(比如数据库连接池、线程池) 
限制瞬时并发数(如nginx限制瞬时并发连接数) 
限制时间窗口内的平均速率(如Guava的RateLimiter、nginx的limit_req模块, 限制每秒的平均速率) 
限制远程接口调用速率、
限制MQ的消费速率等  
Hystrix熔断应用(调用者用)
目的:简历微服务长时间没有响应,服务消费者—>自动投递微服务快速失败给用户提示  
1、消费端可以引入Hystrix依赖坐标
( 服务消费者工程(自动投递微服务) 也可以将依赖坐标添加到父文件中)
<!--熔断器Hystrix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>
2、启动类中添加熔断器开启注解
入口类添加@EnableCircuitBreaker 注解
@SpringBootApplication@EnableDiscoveryClient //开启服务发现//@EnableHystrix // 开启Hystrix功能@EnableCircuitBreaker // 开启熔断器功能(通用性)//@SpringCloudApplication 综合性的注解 (可以代替上面三个)//@SpringCloudApplication=@SpringBootApplication + @EnableDiscoveryClient + @EnableCircuitBreakerpublic class AutodeliverApplication8090 {........
3、定义熔断
扇出方法进行Hystrix控制,把当前要降级处理的方法做一个标识
定义服务降级处理方法,在业务方法上使用@HystrixCommand的 fallbackMethod属性关联到服务降级处理方法 上。熔断后返回的还是异常信息,是500,将返回信息改为兜底的显示。
原理是:会扫描有HystrixCommand此注解,此注解标识的方法就会通过面向切面方法执行
/*** 提供者模拟处理超时,调用方法添加Hystrix控制 */// 使用@HystrixCommand注解进行熔断控制@HystrixCommand(// commandProperties熔断的一些细节属性配置commandProperties = {// 每一个属性都是一个HystrixProperty@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="2000")})@GetMapping("/checkStateTimeout/{userId}")public Integer findResumeOpenStateTimeout(@PathVariable Long userId) {// 使用ribbon不需要我们自己获取服务实例然后选择一个那么去访问了(自己的负载均衡)String url = "http://lagou-service-resume/resume/openstate/" + userId; // 指定服务名Integer forObject = restTemplate.getForObject(url, Integer.class);return forObject;}
4、定义服务降级
(添加一个fallbackMethod = “自定义的回退方法”  // 回退方法)
注意 
fallbackMethod要配降级(兜底)方法,必须和被降级方法相同的方法签名(相同参数列表、相同返回值)** 
可以在类上使用@DefaultProperties注解统一指定整个类中共用的降级(兜 底)方法 
服务提供者端(简历微服务)模拟请求超时(线程休眠3s),只修改8080实 例,8081不修改,对比观察  
/
  1)服务提供者处理超时,熔断,返回错误信息
  2)有可能服务提供者出现异常直接抛出异常信息
  以上信息,都会返回到消费者这里,很多时候消费者服务不希望把收到异常/错误信息再抛到它的上游去
    用户微服务 —  注册微服务  — 优惠券微服务
                1 登记注册
                2 分发优惠券(并不是核心步骤),这里如果调用优惠券微服务返回了异常信息或者是熔断后的错误信     息,这些信息如果抛给用户很不友好
 *       此时,我们可以返回一个兜底数据,预设的默认值(服务降级)** /_
*fallbackMethod后面配置的myFallBack,是直接返回-123333的
@GetMapping("/checkStateTimeoutFallback/{userId}")@HystrixCommand(// commandProperties熔断的一些细节属性配置commandProperties = {// 每一个属性都是一个HystrixProperty@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="2000"),},fallbackMethod = "myFallBack" // 回退方法)public Integer findResumeOpenStateTimeoutFallback(@PathVariable Long userId) {// 使用ribbon不需要我们自己获取服务实例然后选择一个那么去访问了(自己的负载均衡)String url = "http://lagou-service-resume/resume/openstate/" + userId; // 指定服务名Integer forObject = restTemplate.getForObject(url, Integer.class);return forObject;}/*定义回退方法,返回预设默认值注意:该方法形参和返回值与原始方法保持一致*/public Integer myFallBack(Long userId) {return -123333; // 兜底数据(不将异常返回前端)}
Hystrix舱壁模式(线程池隔离策略)
每个方法都分配独立的线程池,方法之间不共用线程池。
单独的为每一个控制方法创建一个线程池的方式,这种模式叫做“舱壁模式”,也是线程隔离的手段  
线程池也是在HystrixCommand注解里面添加的
添加线程唯一标识:threadPoolKey
配置线程的属性:  threadPoolProperties
/*** 提供者模拟处理超时,调用方法添加Hystrix控制 */// 使用@HystrixCommand注解进行熔断控制@HystrixCommand(// 线程池标识,要保持唯一,不唯一的话就共用了threadPoolKey = "findResumeOpenStateTimeout",// 线程池细节属性配置threadPoolProperties = {@HystrixProperty(name="coreSize",value = "1"), // 线程数@HystrixProperty(name="maxQueueSize",value="20") // 等待队列长度},// commandProperties熔断的一些细节属性配置commandProperties = {// 每一个属性都是一个HystrixProperty@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="2000")})@GetMapping("/checkStateTimeout/{userId}")public Integer findResumeOpenStateTimeout(@PathVariable Long userId) {// 使用ribbon不需要我们自己获取服务实例然后选择一个那么去访问了(自己的负载均衡)String url = "http://lagou-service-resume/resume/openstate/" + userId; // 指定服务名Integer forObject = restTemplate.getForObject(url, Integer.class);return forObject;}
Hystrix工作流程与高级应用
1、基于springboot的健康检查观察跳闸状态(客户端微服务暴露健康检查细节)
通过访问健康检查接口详细信息:http://localhost:8090/actuator/health
# springboot中暴露健康检查等断点接口management:endpoints:web:exposure:include: "*"# 暴露健康接口的细节endpoint:health:show-details: always
2、在commandProperties下添加四项时间窗口定义信息定义
@GetMapping("/checkStateTimeoutFallback/{userId}")@HystrixCommand(// 线程池标识,要保持唯一,不唯一的话就共用了threadPoolKey = "findResumeOpenStateTimeoutFallback",// 线程池细节属性配置threadPoolProperties = {@HystrixProperty(name="coreSize",value = "2"), // 线程数@HystrixProperty(name="maxQueueSize",value="20") // 等待队列长度},// commandProperties熔断的一些细节属性配置commandProperties = {// 每一个属性都是一个HystrixProperty@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="2000")// hystrix高级配置,定制工作过程细节如下,// 统计时间窗口定义@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "8000"),// 统计时间窗口内的最小请求数@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "2"),// 统计时间窗口内的错误数量百分比阈值@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),// 自我修复时的活动窗口长度@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "3000")},fallbackMethod = "myFallBack" // 回退方法)public Integer findResumeOpenStateTimeoutFallback(@PathVariable Long userId) {// 使用ribbon不需要我们自己获取服务实例然后选择一个那么去访问了(自己的负载均衡)String url = "http://lagou-service-resume/resume/openstate/" + userId; // 指定服务名Integer forObject = restTemplate.getForObject(url, Integer.class);return forObject;}
Hystrix Dashboard断路监控仪表盘
工程中需要引入SpringBoot的actuator(健康监控),它提供了很多监控所需的接口,可以对应用系统进行配置查看、相关功能统计等 。、
1、可以添加到父的配置文件中
<!-- Actuator可以帮助你监控和管理Spring Boot应用--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
如果我们想看到Hystrix相关数据,比如有多少请求、多少成功、多少失败、多少降 级等,那么引入SpringBoot健康监控之后,访问/actuator/hystrix.stream接口可以 获取到监控的文字信息,但是不直观,所以Hystrix官方还提供了基于图形化的 DashBoard(仪表板)监控平台。Hystrix仪表板可以显示每个断路器(被 @HystrixCommand注解的方法)的状态。
2、创建一个仪表盘项目并引入jar
<!--hystrix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency><!--hystrix 仪表盘--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
3、启动类开启仪表盘功能
@SpringBootApplication@EnableDiscoveryClient@EnableHystrixDashboard // 开启hystrix dashboardpublic class HystrixDashboard9000 {public static void main(String[] args) {SpringApplication.run(HystrixDashboard9000.class,args);}}
4、添加yam.xml的配置文件
server:port: 9000Spring:application:name: lagou-cloud-hystrix-dashboardeureka:client:serviceUrl: # eureka server的路径defaultZone: http://lagoucloudeurekaservera:8761/eureka/,http://lagoucloudeurekaserverb:8762/eureka/ #把 eureka 集群中的所有 url 都填写了进来,也可以只写一台,因为各个 eureka server 可以同步注册表instance:#使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)prefer-ip-address: true#自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddressinstance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
5、 在被监测的微服务中注册监控的servlet方法(固定的)
(自动投递微服务(被监控的客户端),监控数据就是来源于这 个微服务)看这个客户端发送信息情况
/*** 在被监控的微服务中注册一个serlvet,后期我们就是通过访问这个servlet来获取该服务的Hystrix监控数据的* 前提:被监控的微服务需要引入springboot的actuator功能* @return*/@Beanpublic ServletRegistrationBean getServlet(){HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);registrationBean.setLoadOnStartup(1);registrationBean.addUrlMappings("/actuator/hystrix.stream");registrationBean.setName("HystrixMetricsStreamServlet");return registrationBean;}
6、访问测试http://localhost:9000/hystrix
输入监控的微服务端点地址,展示监控的详细数据,比如监控服务消费者http://locahost:8090/actuator/hystrix.stream
 百分比,10s内错误请求百分比 
 实心圆: 
   大小:代表请求流量的大小,流量越大的球越大
   颜色:代表请求处理的健康状态,从绿色到红色递减,绿代色表健康,红就代 表很不健康 曲
线波动图: 记录了2分钟内该方法上流量的变化波动图,判断流量上升或者下降的趋势  
  
Hystrix Turbine聚合监控
之前是一个微服务实例的Hystrix数据查询分析,在微服务架构下,一个微服务的实例往往是多个(集群化)  
如果一个微服务部署多个实例  使用Hystrix Turbine 进行聚合监控,它可以把相关微服务的监控数据聚合在一起,便于查看。  
1、在pom引入坐标
<!--hystrix turbine聚合监控--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-turbine</artifactId></dependency><!--引入eureka客户端的两个原因1、老师说过,微服务架构下的服务都尽量注册到服务中心去,便于统一管理2、后续在当前turbine项目中我们需要配置turbine聚合的服务,比如,我们希望聚合lagou-service-autodeliver这个服务的各个实例的hystrix数据流,那随后我们就需要在application.yml文件中配置这个服务名,那么turbine获取服务下具体实例的数据流的时候需要ip和端口等实例信息,那么怎么根据服务名称获取到这些信息呢?当然可以从eureka服务注册中心获取--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
2、在工程application.yml中开启 Turbine及进行相关配置
将需要进行Hystrix监控的多个微服务配置起来,
server:port: 9001Spring:application:name: lagou-cloud-hystrix-turbineeureka:client:serviceUrl: # eureka server的路径defaultZone: http://lagoucloudeurekaservera:8761/eureka/,http://lagoucloudeurekaserverb:8762/eureka/ #把 eureka 集群中的所有 url 都填写了进来,也可以只写一台,因为各个 eureka server 可以同步注册表instance:#使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)prefer-ip-address: true#自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddressinstance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@#turbine配置turbine:# appCofing配置需要聚合的服务名称,比如这里聚合自动投递微服务的hystrix监控数据# 如果要聚合多个微服务的监控数据,那么可以使用英文逗号拼接,比如 a,b,cappConfig: lagou-service-autodeliverclusterNameExpression: "'default'" # 集群默认名称
3、开启仪表盘以及Turbine聚合功能
在当前项目启动类上添加注解@EnableTurbine
@SpringBootApplication@EnableDiscoveryClient@EnableTurbine // 开启Turbine聚合功能public class HystrixTurbineApplication9001 {public static void main(String[] args) {SpringApplication.run(HystrixTurbineApplication9001.class,args);}}
4、 通过dashboard直观的查看数据

============================
