目录

1 服务雪崩效应

2 重要概念

2.1 服务降级

哪些情况会出现服务降级

2.2 服务熔断

2.3 服务限流

3 服务降级实测(服务提供者)

3.1 pom.xml

3.2 application.yml

3.3 主启动类

3.4 业务类

3.5 测试

4 服务降级实测(服务调用者)

4.1 pom.xml

4.2 application.yml

4.3 启动类

4.4 业务类

5 服务熔断

5.1 测试代码


1 服务雪崩效应

多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,即服务雪崩。

服务雪崩效应是一种因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程。(注:此定义来自某些博客大神,无法确定出处)

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列、线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都意味着需要对故障和延迟进行隔离和管理,防止单个依赖的失败,不会影响到整个应用程序或系统。

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

2 重要概念

2.1 服务降级

服务器忙,请稍后再试,不让客户端等待并返回一个友好提示,这个友好提示其实就是一个兜底方案。

哪些情况会出现服务降级

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

2.2 服务熔断

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

流程为:服务熔断->服务降级->恢复调用链路。

2.3 服务限流

秒杀高并发操作,严禁一窝蜂的过来拥挤,大家排队,一秒N个,有序进行。有点类似春节时火车站的限流场景。

3 服务降级实测(服务提供者)

3.1 pom.xml

<?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>cloud2020</artifactId><groupId>com.bighuan.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><!--引入自定义的api通用包,可以使用Payment支付Entity--><dependency><groupId>com.bighuan.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><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.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><!-- <version>1.1.10</version>--></dependency><!--mysql connector--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</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><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><mainClass>com.bighuan.springcloud.PaymentHystrixMain8001</mainClass></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>

3.2 application.yml

注意:数据库相关配置与测试服务降级无关

server:port: 8001spring:application:name: cloud-provider-hystrix-payment-servicedatasource:type: com.alibaba.druid.pool.DruidDataSource   # 当前数据源操作类型driver-class-name: org.gjt.mm.mysql.Driver    # mysql驱动包url: jdbc:mysql://127.0.0.1:3306/db2019?useUnicode=true&characterEncoding=UTF-8&useSSL=falseusername: rootpassword: rooteureka:client:# 表示是否将自己注册进Eureka Server,默认为trueregister-with-eureka: true# 是否从Eureka Server获取已有的注册信息,默认为true,单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡fetch-registry: trueservice-url:defaultZone: http://localhost:7001/eureka  # 单机版mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.bighuan.springcloud.entities  # 所有Entity别类名所在包

3.3 主启动类

主启动类上添加了@EnableCircuitBreaker注解,启动断路器功能。

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class PaymentHystrixMain8001 {public static void main(String[] args) {SpringApplication.run(PaymentHystrixMain8001.class, args);}
}

3.4 业务类

接口PaymentService

 /*** 测试hystrix,返回正常的信息* @param id* @return*/String paymentInfoOK(Integer id);/*** 测试hystrix,方法不能正常执行* @param id* @return*/String paymentInfoTimeout(Integer id);

接口实现PaymentServiceImpl

 @Overridepublic String paymentInfoOK(Integer id) {return "线程池:"+Thread.currentThread().getName()+" paymentInfoOK,id:"+id;}@HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandler",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")})@Overridepublic String paymentInfoTimeout(Integer id) {int timeout=3;try {TimeUnit.SECONDS.sleep(timeout);} catch (InterruptedException e) {//  e.printStackTrace();}//int age = 10/0;return "线程池:"+Thread.currentThread().getName()+" paymentInfoTimeout,id:"+id+",耗时(秒)";}// 兜底方法public String paymentInfoTimeoutHandler(Integer id) {return "线程池:"+Thread.currentThread().getName()+" 系统繁忙或运行报错,请稍后再试!,id:"+id+",o(╥﹏╥)o";}

(controller省略)

3.5 测试

a)当接口实现的paymentInfoTimeOut方法中,timeOut=3秒时,并没有超过设置的超时时间5秒,所有可以正常返回信息。(浏览器访问)

b)当接口实现的paymentInfoTimeOut方法的timeOut设置为6秒时,超过设置的超时时间5秒,此时就进入到兜底方法中,返回给用户一个友好提示。浏览器访问)

c)当接口实现的paymentInfoTimeOut方法中,timeOut=3秒时,并没有超过设置的超时时间5秒,但是通过JMeter进行压力测试(设置一个线程组200个线程,每秒发一次,循环100次,共20000个请求),高并发使服务不可用,发现程序立马就进行了服务降级。

但是最后有几个请求得到了成功响应,请求到最后系统压力没那么大了,没有走兜底方法。

4 服务降级实测(服务调用者)

4.1 pom.xml

<?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>cloud2020</artifactId><groupId>com.bighuan.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-consumer-feign-hystrix-order80</artifactId><dependencies><!--Hystrix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency><!-- openfeign --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</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.bighuan.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><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><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><mainClass>com.bighuan.springcloud.OrderFeignHystrixMain80</mainClass></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>

4.2 application.yml

server:port: 80
spring:application:name: cloud-order-service
eureka:instance:instance-id: order${server.port}   #例如:order80prefer-ip-address: true  # 访问路径可以显示ip地址client:# 表示是否将自己注册进Eureka Server,默认为trueregister-with-eureka: true# 是否从Eureka Server获取已有的注册信息,默认为true,单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡fetch-registry: trueservice-url:defaultZone: http://localhost:7001/eureka# defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
ribbon:# 处理请求的超时时间,默认为1秒ReadTimeout: 5000# 连接建立的超时时间,默认1秒ConnectTimeout: 5000
logging:level:# feign日志以什么级别监控哪个接口#com.bighuan.springcloud.service.PaymentFeignService: debugcom.bighuan.springcloud.service: debug
feign:hystrix:# 开启feign的hystrix支持enabled: true

4.3 启动类

@EnableHystrix注解用以激活Hystrix。

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix // 激活Hystrix
public class OrderFeignHystrixMain80 {public static void main(String[] args) {SpringApplication.run(OrderFeignHystrixMain80.class,args);}
}

4.4 业务类

@Component
@FeignClient(name = "CLOUD-PROVIDER-HYSTRIX-PAYMENT-SERVICE",fallback = PaymentFeignHystrixFallbackService.class) // 设置远程服务,将一个远程服务映射为一个本地方法调用
public interface PaymentFeignHystrixService {/*** 查询** @param id* @return*/@GetMapping(value = "/payment/get/{id}")CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);@GetMapping(value = "/payment/feign/timeout")String paymentFeignTimeOut();@GetMapping(value="/payment/hystrix/ok/{id}")public String paymentInfoOK(@PathVariable("id") Integer id);@GetMapping(value="/payment/hystrix/timeout/{id}")public String paymentInfoTimeout(@PathVariable("id") Integer id);
}
@Component
public class PaymentFeignHystrixFallbackService implements PaymentFeignHystrixService {@Overridepublic CommonResult<Payment> getPaymentById(Long id) {return null;}@Overridepublic String paymentFeignTimeOut() {return null;}@Overridepublic String paymentInfoOK(Integer id) {return "-----PaymentFeignHystrixFallbackService fall back -paymentInfoOK,o(╥﹏╥)o";}@Overridepublic String paymentInfoTimeout(Integer id) {return "-----PaymentFeignHystrixFallbackService fall back -paymentInfoTimeout,o(╥﹏╥)o";}
}
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "paymentGlobalFallBackMethod")
public class OrderHystrixFeignController {
// 有特殊指定的兜底方法/* @HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandler",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")})*/// 使用全局默认的兜底方法@HystrixCommand@GetMapping(value = "/consumer/payment/hystrix/timeout/{id}")public String paymentInfoTimeout(@PathVariable("id") Integer id) {int age =10/0;String result = paymentFeignHystrixService.paymentInfoTimeout(id);return result;}// 兜底方法public String paymentInfoTimeoutHandler(Integer id) {return "我是消费者80,对方支付系统繁忙,请10秒钟后重新尝试或者自身运行出错,请检查自己!!!o(╥﹏╥)o";}// 下面是全局fallback方法,全局默认的兜底方法public String paymentGlobalFallBackMethod(){return "Global异常处理信息,请稍后再试!o(╥﹏╥)o";}
}

说明如下

代码膨胀问题:

a)如果每个方法都要做一个方法进行服务降级,那么会导致代码膨胀的问题,那么此时可以通过全局服务降级来避免该问题。

@DefaultProperties(defaultFallback = "paymentGlobalFallBackMethod")

如果一个方法有指定兜底方法,那么就走指定的兜底方法;如果没有指定兜底方法,但是配置了全局兜底方法(使用了注解@HystrixCommand),就走全局的兜底方法。

代码混乱问题:

每一个方法都要对应一个兜底方法的话,如果都在同一个类或接口中,那么代码是比较混乱的。所以可以通过接口和对应的实现来解决代码混乱问题。

如上代码,PaymentFeignHystrixService是一个FeignClient,这个接口对应的实现即为服务降级对应的方法。需要在PaymentFeignHystrixService上添加如下对应的fallback配置。

@FeignClient(name = "CLOUD-PROVIDER-HYSTRIX-PAYMENT-SERVICE",fallback = PaymentFeignHystrixFallbackService.class)

对应的测试与第三章节类似,不赘述。

5 服务熔断

(说明:此章节在第三章节基础上进行测试)

5.1 测试代码

增加对应的测试代码

PaymentService:

  /*** 测试服务熔断* @param id* @return*/String paymentCircuitBreaker(Integer id);

PaymentServiceImpl:

 /***********服务熔断**********/@HystrixCommand(fallbackMethod = "paymentCircuitBreakerFallback",commandProperties={@HystrixProperty(name="circuitBreaker.enabled",value = "true"), // 是否看齐断路器@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"), // 请求次数@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="10000"), // 时间窗口期@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="10") // 当失败率达到多少后就跳闸})@Overridepublic String paymentCircuitBreaker( Integer id){if(id < 0){throw new RuntimeException("************id为负数");}String serialNumber= IdUtil.simpleUUID();return Thread.currentThread().getName()+"调用成功,流水号为:"+serialNumber;}public String paymentCircuitBreakerFallback(@PathVariable("id") Integer id){return "id:"+id+"不能为负数,请稍后再试!o(╥﹏╥)o";}

涉及断路器的几个重要重要参数(Hystrix相关配置)

a)circuitBreaker.enabled :是否开启断路器

b)circuitBreaker.requestVolumeThreshold :请求总数阈值,在快照时间窗内,必须满足请求总数阈值才有资格熔断,默认为20次,即在快照时间窗内,若Hystrix命令的调用次数不足20次,即使所有请求超时或其他原因失败,也不会打开断路器。

c)circuitBreaker.sleepWindowInMilliseconds :快照时间窗,断路器确定是否打开需要统计请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的5秒。

d)circuitBreaker.errorThresholdPercentage:错误百分比阈值,当请求总数在快照时间窗内超过了阈值,比如30次调用,发生了15次超时异常,即超过50%的错误率,在默认设定50%的阈值情况下,此时断路器就会打开。

controller:

  /************服务熔断**************/@GetMapping(value="/payment/circuit/{id}")public String paymentCircuitBreaker(@PathVariable("id") Integer id){String result = paymentService.paymentCircuitBreaker(id);return result;}

测试:

a)当一个快照时间窗同时满足了请求总数阈值、错误百分比阈值,那么断路器将会开启。当断路器开启的时候,所有请求都不会进行转发。

b)当一个时间窗后,断路器会切换为半开状态,会让其中一个请求进行转发,转发成功,断路器关闭,否则继续开启,并按上述步骤重复尝试关闭断路器。

微服务学习之Hystrix容错保护【Hoxton.SR1版】相关推荐

  1. Spring Cloud构建微服务架构:Hystrix监控面板【Dalston版】

    在上一篇<服务容错保护(hystrix断路器)>的介绍中,我们提到断路器是根据一段时间窗内的请求情况来判断并操作断路器的打开和关闭状态的.而这些请求情况的指标信息都是HystrixComm ...

  2. 微服务架构之「 容错隔离 」

    点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! 我们知道,在单体应用的架构下一旦程序发生了故障,那么整个应用可能就没法使用了,所以我们要把单体应 ...

  3. .NET Core 微服务学习与实践系列文章目录索引(2019版)

    Photo :.NET Core 文 | Edison Zhou 2018年,我开始学习和实践.NET Core,并开始了微服务的学习,以及通过各种开源组件搭建服务治理技术方案,并在学习过程中总结了一 ...

  4. Spring Cloud构建微服务架构:Hystrix监控数据聚合【Dalston版】

    上一篇我们介绍了使用Hystrix Dashboard来展示Hystrix用于熔断的各项度量指标.通过Hystrix Dashboard,我们可以方便的查看服务实例的综合情况,比如:服务调用次数.服务 ...

  5. Java微服务学习笔记(一):微服务架构的概念理解

    Java微服务学习笔记 Tips:入门学习时粗略整理,仅供参考 (一):架构的基础理解 文章目录 Java微服务学习笔记 前言 一.微服务是什么? 二.常用开源微服务框架演化 1. Dubbo 2. ...

  6. 微服务学习总结4(网关和consul结合)

    先上一张图片: 首先要启动consul服务,用于对三个日志服务的注册和发现.(默认端口8500) 然后启动三个日志服务,端口分别为5726.5727.5728. 最后启动网关服务,用于转发客户端请求, ...

  7. Spring Cloud构建微服务架构:分布式配置中心【Dalston版】

    Spring Cloud Config是Spring Cloud团队创建的一个全新项目,用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,它分为服务端与客户端两个部分.其中服务端也称为 ...

  8. 微服务组件之Hystrix豪猪简介和简单学习-2021-8-20

    Hystrix 豪猪,在微服务系统中是一款提供保护机制的组件 当服务请求太多的时候,每个依赖关系在某些时候将不可避免地失败.Hystrix可以提供服务熔断和服务降级来解决这类问题,我们称之为熔断器,返 ...

  9. Spring Cloud 微服务学习与实践

    第一章:微服务架构概述 1-1. 系统进化理论概述 在系统架构与设计的实践中,经历了两个阶段,一个阶段是早些年常见的集中式 系统,一个阶段是近年来流行的分布式系统: 集中式系统: 集中式系统也叫单体应 ...

  10. SpringCloud中Hystrix容错保护原理及配置,看它就够了!

    点击关注公众号,Java干货及时送达 作者:kosamino cnblogs.com/jing99/p/11625306.html 1 什么是灾难性雪崩效应? 如下图的过程所示,灾难性雪崩形成原因就大 ...

最新文章

  1. python数据库gui_从python数据库在gui上打印数据
  2. iis错误Server Application Error的解决方法(附修复工具下载)
  3. Eclipse下配置struts很让我痛苦
  4. 根据姓名得到名字首字母
  5. Unix系统编程()main函数的命令行参数
  6. C#来创建和读取XML文档 [转]
  7. Java文件保存与删除工具类
  8. dao传递类参数 mybatis_Mybatis (ParameterType) 如何传递多个不同类型的参数
  9. Opencv 图片缩小尺寸原理
  10. 信息学奥赛一本通(1136:密码翻译)
  11. 【Matplotlib】详解图像各个部分
  12. HDU1542--Atlantis(扫描线)
  13. 盛夏光年——14年暑期总结
  14. 【Spark】Spark调优 资源调优
  15. treeReduce和reduce
  16. tomcat ---- web.xml
  17. Dos命令将合并两个文本文件的内容
  18. 前端面试每日 3+1 —— 第27天
  19. Access2010中文版入门与实例教程(奋斗的小鸟)_PDF 电子书
  20. TFT-LCD显示屏工作原理图文解析

热门文章

  1. Fintech生态报告:区块链是金融业革新的王牌技术
  2. 一起谈.NET技术,ASP.NET Routing对请求的处理方式
  3. 52.Linux/Unix 系统编程手册(下) -- POSIX 消息队列
  4. 28.TCP/IP 详解卷1 --- SMTP:简单邮件传输协议
  5. 18. strings
  6. 52. 配置 Etag (13)
  7. 计算机动画原理课程设计,Flash动画优化的原理和常用优化方式,毕业论文,课程设计,PPT,开发报告,外文翻译 - 论文助手...
  8. python numpy和pandas做数据分析时去掉科学记数法显示
  9. 个人总结OLinux上安装oracle11G Data Guard
  10. 多线程--对象及变量的并发访问