本笔记内容为尚硅谷SpringCloud框架开发Hystrix部分

目录

一、概述

二、Hystrix重要概念

1、服务降级

2、服务熔断

3、服务限流

三、hystrix案例

1、案例创建和测试

1.构建

2.高并发测试

3.故障现象和导致原因

4.如何解决?解决的要求

2、服务降级

1.提供者8001fallback

2.消费者80fallback

3.目前问题

4.解决问题

3、服务熔断

1.熔断是什么

2.实操

3.原理(小总结)

4、服务限流

四、hystrix工作流程

官网图例

步骤说明

五、服务监控hystrixDashboard

1、概述

2、创建Module仪表盘9001

3、断路器演示(服务监控hystrixDashboard)

1.修改cloud-provider-hystrix-payment8001

2.监控测试


一、概述


Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

作用:

  • 服务降级
  • 服务熔断
  • 接近实时的监控

官网资料:How To Use · Netflix/Hystrix Wiki · GitHub

Hystrix停更:https://github.com/Netflix/Hystrix

被动修复bugs、不再接受合并请求、不再发布新版本

二、Hystrix重要概念


1、服务降级

服务器忙,请稍后再试,不让客户端等待并立刻返回一个友好提示,fallback。

哪些情况会出发降级:

  • 程序运行异常
  • 超时
  • 服务熔断触发服务降级
  • 线程池/信号量打满也会导致服务降级

2、服务熔断

类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示。就是保险丝

服务的降级->进而熔断->恢复调用链路

3、服务限流

秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行

三、hystrix案例


1、案例创建和测试

1.构建

新建cloud-provider-hystrix-payment8001

POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>mscloud03</artifactId><groupId>com.atguigu.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-provider-hystrix-payment8001</artifactId><dependencies><!--hystrix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency><!--eureka client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><groupId>com.atguigu.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>

YML

server:port: 8001spring:application:name: cloud-provider-hystrix-paymenteureka:client:register-with-eureka: truefetch-registry: trueservice-url:#defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eurekadefaultZone: http://eureka7001.com:7001/eureka

主启动

package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication
@EnableEurekaClient //本服务启动后会自动注册进eureka服务中
public class PaymentHystrixMain8001
{public static void main(String[] args){SpringApplication.run(PaymentHystrixMain8001.class,args);}
}

业务类

service包下的PaymentService.java

package com.atguigu.springcloud.service;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;import java.util.concurrent.TimeUnit;@Service
public class PaymentService
{/*** 正常访问,一切OK* @param id* @return*/public String paymentInfo_OK(Integer id){return "线程池:"+Thread.currentThread().getName()+"paymentInfo_OK,id: "+id+"\t"+"O(∩_∩)O";}/*** 超时访问,演示降级* @param id* @return*/public String paymentInfo_TimeOut(Integer id){try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }return "线程池:"+Thread.currentThread().getName()+"paymentInfo_TimeOut,id: "+id+"\t"+"O(∩_∩)O,耗费3秒";}
}

controller包下的PaymentController.java

package com.atguigu.springcloud.controller;import com.atguigu.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;@RestController
@Slf4j
public class PaymentController
{@Autowiredprivate PaymentService paymentService;@Value("${server.port}")private String serverPort;@GetMapping("/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id){String result = paymentService.paymentInfo_OK(id);log.info("****result: "+result);return result;}@GetMapping("/payment/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id) throws InterruptedException{String result = paymentService.paymentInfo_TimeOut(id);log.info("****result: "+result);return result;}
}

正常测试

启动eureka7001

启动cloud-provider-hystrix-payment8001

访问:

success的方法:http://localhost:8001/payment/hystrix/ok/31

每次调用耗费5秒钟:http://localhost:8001/payment/hystrix/timeout/31

上述module均OK,以上述为根基平台,从正确->错误->降级熔断->恢复

2.高并发测试

上述在非高并发情形下,还能勉强满足

Jmeter压测测试

开启Jmeter,来20000个并发压死8001,20000个请求都去访问paymentInfo_TimeOut服务

访问:http://localhost:8001/payment/hystrix/ok/31

结果:两个都在自己转圈圈

原因:tomcat的默认的工作线程数被打满 了,没有多余的线程来分解压力和处理。

Jmeter压测结论

上面还是服务提供者8001自己测试,假如此时外部的消费者80也来访问,那消费者只能干等,最终导致消费端80不满意,服务端8001直接被拖死。

consumer80新建加入

①新建cloud-consumer-feign-hystrix-order80

②POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>mscloud03</artifactId><groupId>com.atguigu.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-consumer-feign-hystrix-order80</artifactId><dependencies><!--openfeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--hystrix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency><!--eureka client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><dependency><groupId>com.atguigu.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--一般基础通用配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>

③YML

server:port: 80eureka:client:register-with-eureka: falseservice-url:defaultZone: http://eureka7001.com:7001/eureka/

④主启动

package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableFeignClients
public class OrderHystrixMain80
{public static void main(String[] args){SpringApplication.run(OrderHystrixMain80.class,args);}
}

⑤业务类

service包下的PaymentHystrixService.java

package com.atguigu.springcloud.service;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface PaymentHystrixService
{@GetMapping("/payment/hystrix/ok/{id}")String paymentInfo_OK(@PathVariable("id") Integer id);@GetMapping("/payment/hystrix/timeout/{id}")String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}

controller包下的OrderHystirxController.java

package com.atguigu.springcloud.controller;import com.atguigu.springcloud.service.PaymentHystrixService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
@Slf4j
public class OrderHystirxController
{@Resourceprivate PaymentHystrixService paymentHystrixService;@GetMapping("/consumer/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id){String result = paymentHystrixService.paymentInfo_OK(id);return result;}@GetMapping("/consumer/payment/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id){String result = paymentHystrixService.paymentInfo_TimeOut(id);return result;}
}

正常测试:http://localhost/consumer/payment/hystrix/ok/31

高并发测试

2W个线程压8001

消费端80微服务再去访问正常的Ok微服务8001地址http://localhost/consumer/payment/hystrix/ok/32

结果:消费者80,o(╥﹏╥)o、要么转圈圈等待要么消费端报超时错误

3.故障现象和导致原因

8001同一层次的其它接口服务被困死,因为tomcat线程池里面的工作线程已经被挤占完毕

80此时调用8001,客户端访问响应缓慢,转圈圈

结论:正因为有上述故障或不佳表现才有我们的降级/容错/限流等技术诞生

4.如何解决?解决的要求

超时导致服务器变慢(转圈):超时不再等待

出错(宕机或程序运行出错):出错要有兜底

解决

  • 对方服务(8001)超时了,调用者(80)不能一直卡死等待,必须有服务降级
  • 对方服务(8001)down机了,调用者(80)不能一直卡死等待,必须有服务降级
  • 对方服务(8001)OK,调用者(80)自己出故障或有自我要求(自己的等待时间小于服务提供者),自己处理降级

2、服务降级

降级配置@HystrixCommand

8001先从自身找问题:设置自身调用超时时间的峰值,峰值内可以正常运行,超过了需要有兜底的方法处理,作服务降级fallback。

1.提供者8001fallback

业务类启用

package com.atguigu.springcloud.service;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;import java.util.concurrent.TimeUnit;@Service
public class PaymentService
{/*** 正常访问,一切OK* @param id* @return*/public String paymentInfo_OK(Integer id){return "线程池:"+Thread.currentThread().getName()+"paymentInfo_OK,id: "+id+"\t"+"O(∩_∩)O";}/*** 超时访问,演示降级* @param id* @return*/@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")})public String paymentInfo_TimeOut(Integer id){int second = 5;try { TimeUnit.SECONDS.sleep(second); } catch (InterruptedException e) { e.printStackTrace(); }return "线程池:"+Thread.currentThread().getName()+"paymentInfo_TimeOut,id: "+id+"\t"+"O(∩_∩)O,耗费秒: "+second;}public String paymentInfo_TimeOutHandler(Integer id){return "/(ㄒoㄒ)/调用支付接口超时或异常:\t"+ "\t当前线程池名字" + Thread.currentThread().getName();}
}

@HystrixCommand报异常后如何处理

一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法。

主启动类激活

添加新注解@EnableCircuitBreaker

2.消费者80fallback

大部分服务降级用在客户端

80订单微服务,也可以更好的保护自己,自己也依样画葫芦进行客户端降级保护

注意:我们自己配置过的热部署方式对java代码的改动明显,但对@HystrixCommand内属性的修改建议重启微服务

①YML

server:port: 80eureka:client:register-with-eureka: falseservice-url:defaultZone: http://eureka7001.com:7001/eureka/feign:hystrix:enabled: true

②主启动

package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class OrderHystrixMain80
{public static void main(String[] args){SpringApplication.run(OrderHystrixMain80.class,args);}
}

③业务类

package com.atguigu.springcloud.controller;import com.atguigu.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
@Slf4j
public class PaymentHystirxController
{@Resourceprivate PaymentHystrixService paymentHystrixService;@GetMapping("/consumer/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id){String result = paymentHystrixService.paymentInfo_OK(id);return result;}@GetMapping("/consumer/payment/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
})
public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
{String result = paymentHystrixService.paymentInfo_TimeOut(id);return result;
}
public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id)
{return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
}}

3.目前问题

每个业务方法对应一个兜底的方法,代码膨胀

统一和自定义的分开

4.解决问题

①每个方法配置一个???膨胀

feign接口系列:@DefaultProperties(defaultFallback = "")

 controller配置

package com.atguigu.springcloud.controller;import com.atguigu.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
@Slf4j
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class PaymentHystirxController
{@Resourceprivate PaymentHystrixService paymentHystrixService;@GetMapping("/consumer/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id){String result = paymentHystrixService.paymentInfo_OK(id);return result;}@GetMapping("/consumer/payment/hystrix/timeout/{id}")@HystrixCommand //加了@DefaultProperties属性注解,并且没有写具体方法名字,就用统一全局的public String paymentInfo_TimeOut(@PathVariable("id") Integer id){String result = paymentHystrixService.paymentInfo_TimeOut(id);return result;}public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id){return "paymentTimeOutFallbackMethod,对方系统繁忙,请10秒钟后再次尝试/(ㄒoㄒ)/";}public String payment_Global_FallbackMethod(){return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";}
}

②和业务逻辑混一起???混乱

服务降级,客户端去调用服务端,碰上服务端宕机或关闭

本次案例服务降级处理是在客户端80实现完成的,与服务端8001没有关系只需要为Feign客户端定义的接口添加一个服务降级处理的实现类即可实现解耦

未来我们要面对的异常:运行、超时、宕机

业务类PaymentController

1.根据cloud-consumer-feign-hystrix-order80已经有的PaymentHystrixService接口,重新新建一个类(PaymentFallbackService)实现该接口,统一为接口里面的方法进行异常处理。

PaymentFallbackService类实现PaymentHystrixService接口

package com.atguigu.springcloud.service;import org.springframework.stereotype.Component;@Component //必须加 //必须加 //必须加
public class PaymentFallbackService implements PaymentHystrixService
{@Overridepublic String getPaymentInfo(Integer id){return "服务调用失败,提示来自:cloud-consumer-feign-order80";}
}

2.YML

server:port: 80eureka:client:register-with-eureka: falseservice-url:defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
#logging:
#  level:
#    # feign日志以什么级别监控哪个接口
#    com.atguigu.springcloud.service.PaymentFeignClientService: debug# 用于服务降级 在注解@FeignClient中添加fallbackFactory属性值
feign:hystrix:enabled: true #在Feign中开启Hystrix

3.PaymentFeignClientService接口

package com.atguigu.springcloud.service;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
public interface PaymentFeignClientService
{@GetMapping("/payment/hystrix/{id}")public String getPaymentInfo(@PathVariable("id") Integer id);
}

测试

  • 单个eureka先启动
  • 7001PaymentHystrixMain8001启动
  • 正常访问测试:http://localhost/consumer/payment/hystrix/ok/31
  • 故意关闭微服务8001
  • 客户端自己调用提示:此时服务端provider已经down了,但是我们做了服务降级处理,让客户端在服务端不可用时也会获得提示信息而不会挂起耗死服务器

3、服务熔断

1.熔断是什么

熔断机制概述

熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务出错不可用或者响应时间太长时,

会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。

当检测到该节点微服务调用响应正常后,恢复调用链路。

在Spring Cloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,

当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是@HystrixCommand。

相关论文:https://martinfowler.com/bliki/CircuitBreaker.html

2.实操

修改cloud-provider-hystrix-payment8001

PaymentService.java

//=========服务熔断
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id)
{if(id < 0){throw new RuntimeException("******id 不能负数");}String serialNumber = IdUtil.simpleUUID();return Thread.currentThread().getName()+"\t"+"调用成功,流水号: " + serialNumber;
}
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id)
{return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~   id: " +id;
}

PaymentController.java

@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id)
{String result = paymentService.paymentCircuitBreaker(id);log.info("****result: "+result);return result;
}

测试

自测cloud-provider-hystrix-payment8001

正确:http://localhost:8001/payment/circuit/31

错误:http://localhost:8001/payment/circuit/-31

一次正确一次错误trytry、多次错误,然后慢慢正确,发现刚开始不满足条件,就算是正确的访问地址也不能进行

3.原理(小总结)

结论:

 熔断类型

  • 熔断打开:请求不再进行调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态
  • 熔断关闭:熔断关闭不会对服务进行熔断
  • 熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断

官网断路器流程图

断路器在什么情况下开始起作用

 断路器开启或者关闭的条件

  • 当满足一定的阀值的时候(默认10秒内超过20个请求次数)
  • 当失败率达到一定的时候(默认10秒内超过50%的请求失败)
  • 到达以上阀值,断路器将会开启当开启的时候,所有请求都不会进行转发
  • 一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。如果成功,断路器会关闭,若失败,继续开启。重复4和5

断路器打开之后

1:再有请求调用的时候,将不会调用主逻辑,而是直接调用降级fallback。通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果。

2:原来的主逻辑要如何恢复呢?

对于这一问题,hystrix也为我们实现了自动恢复功能。

当断路器打开,对主逻辑进行熔断之后,hystrix会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑,

当休眠时间窗到期,断路器将进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合,

主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时。

All配置

//========================All
@HystrixCommand(fallbackMethod = "str_fallbackMethod",groupKey = "strGroupCommand",commandKey = "strCommand",threadPoolKey = "strThreadPool",commandProperties = {// 设置隔离策略,THREAD 表示线程池 SEMAPHORE:信号池隔离@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),// 当隔离策略选择信号池隔离的时候,用来设置信号池的大小(最大并发数)@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"),// 配置命令执行的超时时间@HystrixProperty(name = "execution.isolation.thread.timeoutinMilliseconds", value = "10"),// 是否启用超时时间@HystrixProperty(name = "execution.timeout.enabled", value = "true"),// 执行超时的时候是否中断@HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "true"),// 执行被取消的时候是否中断@HystrixProperty(name = "execution.isolation.thread.interruptOnCancel", value = "true"),// 允许回调方法执行的最大并发数@HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "10"),// 服务降级是否启用,是否执行回调函数@HystrixProperty(name = "fallback.enabled", value = "true"),// 是否启用断路器@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),// 该属性用来设置在滚动时间窗中,断路器熔断的最小请求数。例如,默认该值为 20 的时候,// 如果滚动时间窗(默认10秒)内仅收到了19个请求, 即使这19个请求都失败了,断路器也不会打开。@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),// 该属性用来设置在滚动时间窗中,表示在滚动时间窗中,在请求数量超过// circuitBreaker.requestVolumeThreshold 的情况下,如果错误请求数的百分比超过50,// 就把断路器设置为 "打开" 状态,否则就设置为 "关闭" 状态。@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),// 该属性用来设置当断路器打开之后的休眠时间窗。 休眠时间窗结束之后,// 会将断路器置为 "半开" 状态,尝试熔断的请求命令,如果依然失败就将断路器继续设置为 "打开" 状态,// 如果成功就设置为 "关闭" 状态。@HystrixProperty(name = "circuitBreaker.sleepWindowinMilliseconds", value = "5000"),// 断路器强制打开@HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),// 断路器强制关闭@HystrixProperty(name = "circuitBreaker.forceClosed", value = "false"),// 滚动时间窗设置,该时间用于断路器判断健康度时需要收集信息的持续时间@HystrixProperty(name = "metrics.rollingStats.timeinMilliseconds", value = "10000"),// 该属性用来设置滚动时间窗统计指标信息时划分"桶"的数量,断路器在收集指标信息的时候会根据// 设置的时间窗长度拆分成多个 "桶" 来累计各度量值,每个"桶"记录了一段时间内的采集指标。// 比如 10 秒内拆分成 10 个"桶"收集这样,所以 timeinMilliseconds 必须能被 numBuckets 整除。否则会抛异常@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),// 该属性用来设置对命令执行的延迟是否使用百分位数来跟踪和计算。如果设置为 false, 那么所有的概要统计都将返回 -1。@HystrixProperty(name = "metrics.rollingPercentile.enabled", value = "false"),// 该属性用来设置百分位统计的滚动窗口的持续时间,单位为毫秒。@HystrixProperty(name = "metrics.rollingPercentile.timeInMilliseconds", value = "60000"),// 该属性用来设置百分位统计滚动窗口中使用 “ 桶 ”的数量。@HystrixProperty(name = "metrics.rollingPercentile.numBuckets", value = "60000"),// 该属性用来设置在执行过程中每个 “桶” 中保留的最大执行次数。如果在滚动时间窗内发生超过该设定值的执行次数,// 就从最初的位置开始重写。例如,将该值设置为100, 滚动窗口为10秒,若在10秒内一个 “桶 ”中发生了500次执行,// 那么该 “桶” 中只保留 最后的100次执行的统计。另外,增加该值的大小将会增加内存量的消耗,并增加排序百分位数所需的计算时间。@HystrixProperty(name = "metrics.rollingPercentile.bucketSize", value = "100"),// 该属性用来设置采集影响断路器状态的健康快照(请求的成功、 错误百分比)的间隔等待时间。@HystrixProperty(name = "metrics.healthSnapshot.intervalinMilliseconds", value = "500"),// 是否开启请求缓存@HystrixProperty(name = "requestCache.enabled", value = "true"),// HystrixCommand的执行和事件是否打印日志到 HystrixRequestLog 中@HystrixProperty(name = "requestLog.enabled", value = "true"),},threadPoolProperties = {// 该参数用来设置执行命令线程池的核心线程数,该值也就是命令执行的最大并发量@HystrixProperty(name = "coreSize", value = "10"),// 该参数用来设置线程池的最大队列大小。当设置为 -1 时,线程池将使用 SynchronousQueue 实现的队列,// 否则将使用 LinkedBlockingQueue 实现的队列。@HystrixProperty(name = "maxQueueSize", value = "-1"),// 该参数用来为队列设置拒绝阈值。 通过该参数, 即使队列没有达到最大值也能拒绝请求。// 该参数主要是对 LinkedBlockingQueue 队列的补充,因为 LinkedBlockingQueue// 队列不能动态修改它的对象大小,而通过该属性就可以调整拒绝请求的队列大小了。@HystrixProperty(name = "queueSizeRejectionThreshold", value = "5"),}
)
public String strConsumer() {return "hello 2020";
}
public String str_fallbackMethod()
{return "*****fall back str_fallbackMethod";
}

4、服务限流

见后面高级篇讲解alibaba的Sentinel说明

四、hystrix工作流程


https://github.com/Netflix/Hystrix/wiki/How-it-Works

Hystrix工作流程

官网图例

步骤说明

五、服务监控hystrixDashboard


1、概述

除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。

2、创建Module仪表盘9001

①新建cloud-consumer-hystrix-dashboard9001

②POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>mscloud03</artifactId><groupId>com.atguigu.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-consumer-hystrix-dashboard9001</artifactId><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>

③YML

server:port: 9001

④HystrixDashboardMain9001+新注解@EnableHystrixDashboard

package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardMain9001
{public static void main(String[] args){SpringApplication.run(MainApp9001.class,args);}
}

⑤所有Provider微服务提供类(8001/8002/8003)都需要监控依赖配置(POM)

   <!-- actuator监控信息完善 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

⑥启动cloud-consumer-hystrix-dashboard9001该微服务后续将监控微服务8001

访问:http://localhost:9001/hystrix

3、断路器演示(服务监控hystrixDashboard)

1.修改cloud-provider-hystrix-payment8001

注意:新版本Hystrix需要在主启动类MainAppHystrix8001中指定监控路径

不然可能出现:Unable to connect to Command Metric Stream.404

package com.atguigu.springcloud;import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;@SpringBootApplication
@EnableEurekaClient //本服务启动后会自动注册进eureka服务中
@EnableCircuitBreaker//对hystrixR熔断机制的支持
public class MainAppHystrix8001
{public static void main(String[] args){SpringApplication.run(MainAppHystrix8001.class,args);}/***此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑*ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",*只要在自己的项目里配置上下面的servlet就可以了*/
@Bean
public ServletRegistrationBean getServlet() {HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);registrationBean.setLoadOnStartup(1);registrationBean.addUrlMappings("/hystrix.stream");registrationBean.setName("HystrixMetricsStreamServlet");return registrationBean;
}}

2.监控测试

启动1个eureka或者3个eureka集群均可

观察监控窗口

9001监控8001

填写监控地址:http://localhost:8001/hystrix.stream

测试地址

http://localhost:8001/payment/circuit/31http://localhost:8001/payment/circuit/-31

上述测试通过

先访问正确地址,再访问错误地址,再正确地址,会发现图示断路器都是慢慢放开的。

监控结果,成功

监控结果,失败

如何看?

7色

1圈

1线

整图说明

结束!

【SpringCloud框架之Hystrix断路器】相关推荐

  1. SpringCloud 第十章 Hystrix断路器

    一.概述 1.分布式系统面临的问题 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败. 服务雪崩 多个微服务之间调用的时候,假设微服务A调用 ...

  2. SpringCloud与微服务Ⅷ --- Hystrix断路器

    复杂的分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败. 服务雪崩 多个微服务之间调用的时候,假设微服务调用服务B和微服务C,微服务B和微服务C又调用其他服务,这就是 ...

  3. SpringCloud与Hystrix断路器

    服务熔断,服务降级,服务监控的学习笔记: 问题 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败. 服务雪崩 多个微服务之间调用的时候,假设微服务A调用微服务B和 ...

  4. SpringCloud中 Feign结合Hystrix断路器开发。

    Feign结合Hystrix断路器开发: 转载于:https://www.cnblogs.com/longdb/p/10468371.html

  5. 五、Hystrix断路器

    Hystrix断路器 概述 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系,每一个依赖关系在某些时候将不可避免的失败. 服务雪崩 多个微服务之间调用的时候,假如微服务A调用微服务 ...

  6. Hystrix断路器原理及实现(服务降级、熔断、限流)

    Hystrix断路器原理及实现(服务降级.熔断.限流) 分布式系统面临的问题 Hystrix重要概念(面试常考) Hystrix案例 Hystrix 服务提供者 Hystrix 服务消费者 原因与解决 ...

  7. SpringClound——Hystrix断路器

    SpringCloud学习资料汇总超级棒的 如上是我在看文章时忽然看到的一个很好的学习SpringCloud的网站 SpringClound--微服务概述--史上最烂 SpringClound--Sp ...

  8. springCloud框架搭建,添加feign和Zuul

    6.Feign远程调用工具 接着上一篇搭建springCloud框架,Feign作为springCloud框架中的一个组件,而不是一个服务.添加位置:服务消费方. 6.1 首先添加依赖:(pom工程, ...

  9. Netflix Hystrix断路器简介与工作原理

    一.前言? 1.Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种 ...

最新文章

  1. android设置app全局没通知声,从android中的firebase发送通知时没有通知声音
  2. SSDT – Error SQL70001 This statement is not recognized in this context-摘自网络
  3. deap实战_2017中国数学建模大赛_B题_第二题
  4. _M_invoke(_Index_tuple_Indices...)
  5. asp.net文件上传进度条控件(破解版~没有时间限制) 多项自定义
  6. android socket 框架c#,C#与Android Socket通信
  7. python变量名区分大小写_python变量名要不要区分大小写
  8. oracle还原数据库及遇到的问题
  9. 得存一波板子了。。。。
  10. 京沪等地11月房价半年来首涨 平价走量将成主流
  11. IntelliJ IDEA库存在却报错找不到的解决办法
  12. 计算机房空调设计规范,空调机房防火设计规范
  13. PCL XL error Subsystem:KERNEL
  14. Java任务调度表达式,Java定时任务表达式,附带在线表达式生成器链接
  15. java excel 透视_在Java中用Excel创建数据透视表和数据透视图
  16. CUDA编程.cu文件
  17. python io多路复用_【python】-- IO多路复用(select、poll、epoll)介绍及实现
  18. 新的开始之Win7、CentOS 6.4 双系统 硬盘安装
  19. 网易考拉海购Dubbok框架优化详解(学习笔记)
  20. CPU四核八线程和四核四线程的区别

热门文章

  1. 【NCEPU】张汉隆:Python 窗体应用开发实战
  2. Xcode 13.3 cycle in dependencies between targets
  3. nmf算法 python_NMF、CNMF(原理+python实现)
  4. 优秀SLAM系统持续更新
  5. 51nod 1381 硬币游戏
  6. nginx php 缓存时间,nginx expires设置数据过期时间
  7. 2022-2028年中国工控安全产业发展动态及投资前景分析报告
  8. 一看就懂:时间复杂度与空间复杂度
  9. 【教程】潘多拉Pandora-SS+多拨+去广告同时运行配置教(斐讯K1)
  10. 【MAC】如何不利用软件就可以清理电脑系统缓存和内存