阅读本文前可先参考

SpringCloud - Spring Cloud根/父项目,开发准备(二)_MinggeQingchun的博客-CSDN博客

在微服务架构中,一个应用往往由多个服务组成,这些服务之间相互依赖,依赖关系错综复杂。

通常情况下,一个用户请求往往需要多个服务配合才能完成。

如下图所示,我们有3个微服务 订单服务,库存服务,用户服务形成一个微服务系统

请求1需要调用 订单服务,库存服务,用户服务 3个服务才能完成

如果 库存服务 响应延迟或者没有响应,则会造成 订单服务 的线程挂起等待,如果大量的用户请求下订单,或导致大量的请求堆积,引起 订单服务 也不可用,如果还有另外一个服务依赖于 订单服 务,如用户服务,它需要查询用户订单,那么 用户服务 查询订单也会引起大量的延迟和请求积,导致用户服务也不可用

从以上过程可以看出,当微服务系统的一个服务出现故障时,故障会沿着服务的调用链路在系统中疯狂蔓延,最终导致整个微服务系统的瘫痪,这就是“雪崩效应”。为了防止此类事件的发生,微服务架构引入了“熔断器”的一系列服务容错和保护机制。

一、熔断器

熔断器Circuit Breaker)一词来源物理学中的电路知识,它的作用是当线路出现故障时,迅速切断电源以保护电路的安全。

在微服务领域,熔断器最早是由 Martin Fowler 在他发表的 《Circuit Breaker》一文中提出。与物理学中的熔断器作用相似,微服务架构中的熔断器能够在某个服务发生故障后,向服务调用方返回一个符合预期的、可处理的降级响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常。这样就保证了服务调用方的线程不会被长时间、不必要地占用,避免故障在微服务系统中的蔓延,防止系统雪崩效应的发生。

二、Hystrix

Hystrix被称为熔断器(断路器),Spring Cloud Hystrix 是基于 Netflix 公司的开源组件 Hystrix 实现的,它提供了熔断器功能,能够有效地阻止分布式微服务系统中出现联动故障,以提高微服务系统的弹性。Spring Cloud Hystrix 具有服务降级、服务熔断、线程隔离、请求缓存、请求合并以及实时故障监控等强大功能。

在微服务系统中,Hystrix 主要帮我们实现了

1、服务降级

2、请求限流

1、服务降级

Hystrix 提供了服务降级功能,能够保证当前服务不受其他服务故障的影响,提高服务的健壮性。

当某个微服务响应时间过长,发生异常,或者服务不可用了,我们不能把错误信息返回回来,或者让它一直卡在那里,所以要准备一个对应的策略(一个方法),当发生这种问题时,我们直接调用这个备用的方法来快速返回一个默认的结果,让请求得到快速响应

我们可以通过重写 HystrixCommand 的 getFallBack() 方法或 HystrixObservableCommand 的 resumeWithFallback() 方法,使服务支持服务降级

1、新建一个springboot Module(springcloud-6-service-eureka-hystrix-consumer),设置父项目 (服务消费者)

2、添加 hystrix 依赖,spring-cloud-starter-netflix-hystrix

<!-- spring-cloud-starter-netflix-hystrix --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>
<!--继承统一的父项目--><parent><groupId>com.company</groupId><artifactId>springcloud-demo</artifactId><version>1.0.0</version>
<!--        <relativePath/> &lt;!&ndash; lookup parent from repository &ndash;&gt;--></parent><groupId>com.company</groupId><artifactId>springcloud-6-service-eureka-hystrix-consumer</artifactId><version>1.0.0</version><name>springcloud-6-service-eureka-hystrix-consumer</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><!--spring web 起步依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--依赖统一的springcloud-service-commons项目--><dependency><groupId>com.company</groupId><artifactId>springcloud-2-service-common</artifactId><version>1.0.0</version></dependency><!-- springboot 开发自动热部署 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency><!--spring-cloud-starter-netflix-eureka-client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- spring-cloud-starter-netflix-hystrix --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

3、application.prperties配置文件中配置访问端口8081,以及配置超时时间

主要配置

#hystrix 默认超时时间是 1000 毫秒,如果你后端的响应超过此时间,就会触发断路器
#链接超时时长(建立连接后从服务端读取到可用资源所用的时间)
ribbon.ReadTimeout=6000
#feign.client.config.default.read-timeout=6000
#读取超时时长(建立连接所用的时间,适用于网络状况正常的情况下,两端连接所需要的时间)
ribbon.ConnectTimeout=3000
#feign.client.config.default.connect-timeout=3000#如果hystrix.command.default.execution.timeout.enabled为true,则会有两个执行方法超时的配置,一个就是ribbon的ReadTimeout,一个就是熔断器hystrix的timeoutInMilliseconds, 此时谁的值小谁生效;
#如果hystrix.command.default.execution.timeout.enabled为false,则熔断器不进行超时熔断,而是根据ribbon的ReadTimeout抛出的异常而熔断,也就是取决于ribbon的ConnectTimeout,配置的是请求服务的超时时间,除非服务找不到,或者网络原因,这个时间才会生效;
#设置HystrixCommand.run()的执行是否有超时限制
#hystrix.command.default.execution.timeout.enabled=false
#设置调用者等待命令执行的超时限制,超过此时间,HystrixCommand被标记为TIMEOUT,并执行回退逻辑
#hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
server.port=8081#设置应用名称,对应Eureka控制台下 DS Replicas 的 Application
spring.application.name=springcloud-6-service-eureka-hystrix-consumer#每间隔5s,向Eureka服务注册中心发送一次心跳,证明服务是否依然“存活”
eureka.instance.lease-renewal-interval-in-seconds=30
#告诉服务端,如果10s之内没有发送心跳,就代表故障,将本服务踢出
eureka.instance.lease-expiration-duration-in-seconds=60
#告诉服务端,服务实例以IP作为链接,不是取机器名
eureka.instance.prefer-ip-address=false#注册服务实例ID,,服务ID必须唯一
eureka.instance.instance-id=springcloud-6-service-eureka-hystrix-consumer
#注册中心的链接地址  http://localhost:8761/eureka
eureka.client.service-url.defaultZone=http://eureka8761:8761/eureka,http://eureka8762:8762/eureka,http://eureka8763:8763/eureka#hystrix 默认超时时间是 1000 毫秒,如果你后端的响应超过此时间,就会触发断路器
#链接超时时长(建立连接后从服务端读取到可用资源所用的时间)
ribbon.ReadTimeout=6000
#feign.client.config.default.read-timeout=6000
#读取超时时长(建立连接所用的时间,适用于网络状况正常的情况下,两端连接所需要的时间)
ribbon.ConnectTimeout=3000
#feign.client.config.default.connect-timeout=3000#如果hystrix.command.default.execution.timeout.enabled为true,则会有两个执行方法超时的配置,一个就是ribbon的ReadTimeout,一个就是熔断器hystrix的timeoutInMilliseconds, 此时谁的值小谁生效;
#如果hystrix.command.default.execution.timeout.enabled为false,则熔断器不进行超时熔断,而是根据ribbon的ReadTimeout抛出的异常而熔断,也就是取决于ribbon的ConnectTimeout,配置的是请求服务的超时时间,除非服务找不到,或者网络原因,这个时间才会生效;
#设置HystrixCommand.run()的执行是否有超时限制
#hystrix.command.default.execution.timeout.enabled=false
#设置调用者等待命令执行的超时限制,超过此时间,HystrixCommand被标记为TIMEOUT,并执行回退逻辑
#hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000

4、 Springboot启动类上添加@EnableCircuitBreaker 注解或 @EnableHystrix开启断路器功能,也可以使用一个名为@SpringCloudApplication 的注解代替主类上的三个注解@SpringBootApplication @EnableDiscoveryClient @EnableCircuitBreaker

@EnableHystrix  //开启Hystrix的服务熔断降级支持
@EnableFeignClients  //表示开启 Spring Cloud OpenFeign的支持功能
@EnableEurekaClient  //开启 Eureka client服务
@SpringBootApplication
public class EurekaHystrix6ConsumerApplication {public static void main(String[] args) {SpringApplication.run(EurekaHystrix6ConsumerApplication.class, args);}
}

5、使用 springcloud-2-service-common 项目中的 ProviderGoodsRemoteClient  服务接口

@Component
@FeignClient("springcloud-6-service-eureka-hystrix-provider")
//@FeignClient("springcloud-5-service-eureka-openfeign-provider")
public interface ProviderGoodsRemoteClient {/*** 声明一个feign的接口,它的实现是服务提供者的controller实现*/@GetMapping(value = "/eureka/hystrix/service/goodList")
//    @GetMapping(value = "/eureka/openfeign/service/goodList")public List<Goods> goods();
}

6、创建服务提供者访问方法,基于RESTFUL风格

server.port=9001#设置应用名称,对应Eureka控制台下 DS Replicas 的 Application(集群部署服务提供者,Application一致,对应多个eureka.instance.instance-id)
spring.application.name=springcloud-6-service-eureka-hystrix-provider#设置mysql数据库连接信息
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=admin123456#每间隔5s,向Eureka服务注册中心发送一次心跳,证明服务是否依然“存活”
eureka.instance.lease-renewal-interval-in-seconds=5
#告诉服务端,如果10s之内没有发送心跳,就代表故障,将本服务踢出
eureka.instance.lease-expiration-duration-in-seconds=10
#告诉服务端,服务实例以IP作为链接,不是取机器名
eureka.instance.prefer-ip-address=false#注册服务实例ID,,服务ID必须唯一
eureka.instance.instance-id=springcloud-6-service-eureka-hystrix-provider
#注册中心的链接地址  http://localhost:8761/eureka
eureka.client.service-url.defaultZone=http://eureka8761:8761/eureka,http://eureka8762:8762/eureka,http://eureka8763:8763/eureka
@RestController
public class GoodsController {@Autowiredprivate GoodsService goodsService;@GetMapping(value = "/eureka/hystrix/service/goodList")public List<Goods> goodList(){List<Goods> goodsList = goodsService.getAllGoods();System.out.println("查询商品列表成功:");for (Goods good:goodsList) {System.out.println("查询商品:"+ good);}return goodsList;}
}

7、创建服务消费者访问方法,基于RESTFUL风格

注:hystrix 默认超时时间是 1000 毫秒,如果你后端的响应超过此时间,就会触发断路器

我们设置 2个 异常

//1、服务超时,会降级try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}//2、服务异常,会降级/*String str = null;if (str == null) {throw new RuntimeException("服务异常了.");}*/

hystrix 默认超时时间是 1000 毫秒,如果你后端的响应超过此时间,就会触发断路器

1、使用application.properties配置文件中的配置

ribbon.ReadTimeout=6000
ribbon.ConnectTimeout=3000hystrix.command.default.execution.timeout.enabled=true hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000

2、或者此处的

hystrix.command.default.execution.timeout.enabled=true;

application.properties配置文件可以不写 1 中配置

@HystrixProperty(name = "execution.timeout.enabled",value = "true"), @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000") 

如果hystrix.command.default.execution.timeout.enabled为false,则熔断器不进行超时熔断,而是根据ribbon的ReadTimeout抛出的异常而熔断,也就是取决于ribbon的ConnectTimeout,配置的是请求服务的超时时间,除非服务找不到,或者网络原因,这个时间才会生效;

HystrixCommand 注解

fallbackMethod:配置回调方法,即服务降级方法

ignoreExceptions:配置不进入降级方法的异常

commandProperties:hystrix属性设置,包括超时设置

threadPoolkey:线程池唯一标识threadPoolProperties:线程池属性设置,包括核心线程树和队列大小,可以做限流

@RestController
public class GoodsController {//产品服务的接口地址(直连)
//    private final String GOODS_SERVICE_URL = "http://localhost:9001/service/goodList";//产品服务的接口地址 (注册中心服务名)
//    private final String GOODS_SERVICE_EUREKA_HYSTRIX_URL = "http://springcloud-6-service-eureka-hystrix-provider/eureka/hystrix/service/goodList";@Autowiredprivate ProviderGoodsRemoteClient providerGoodsRemoteClient;@Autowiredprivate RestTemplate restTemplate;@GetMapping(value = "/springcloud/eureka/hystrix/goodList")@HystrixCommand(fallbackMethod = "fallback",commandProperties = {/*hystrix 默认超时时间是 1000 毫秒,如果你后端的响应超过此时间,就会触发断路器1、使用application.properties配置文件中的ribbon.ReadTimeout=6000ribbon.ConnectTimeout=3000hystrix.command.default.execution.timeout.enabled=truehystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=50002、或者此处的 hystrix.command.default.execution.timeout.enabled=true;application.properties配置文件可以不写 1 中配置@HystrixProperty(name = "execution.timeout.enabled",value = "true"),@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")如果hystrix.command.default.execution.timeout.enabled为false,则熔断器不进行超时熔断,而是根据ribbon的ReadTimeout抛出的异常而熔断,也就是取决于ribbon的ConnectTimeout,配置的是请求服务的超时时间,除非服务找不到,或者网络原因,这个时间才会生效;* */
//                        @HystrixProperty(name = "execution.timeout.enabled",value = "false"),
//                            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")},ignoreExceptions = Throwable.class)public @ResponseBody Object getGoodList(){//hystrix 默认超时时间是 1000 毫秒,如果你后端的响应超过此时间,就会触发断路器//1、服务超时,会降级try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}//2、服务异常,会降级/*String str = null;if (str == null) {throw new RuntimeException("服务异常了.");}*/// 调用远程的一个controller, restful的调用,通过openfeign这种声明式的远程调用,providerGoodsRemoteClient就像dubbo里面的接口层一样return  providerGoodsRemoteClient.goods();//调用远程的一个controller(Restful风格调用)
//        ResponseEntity<Object> responseEntity = restTemplate.getForEntity(GOODS_SERVICE_EUREKA_HYSTRIX_URL, Object.class);
//        return responseEntity.getBody();}public @ResponseBody Object fallback(Throwable throwable){throwable.printStackTrace();System.out.println(throwable.getMessage());return "/springcloud/eureka/hystrix/goodList 服务降级了";}
}

8、启动Eureka(springcloud-3-service-eureka) ,服务提供者(springcloud-6-service-eureka-hystrix-provider),服务消费者(springcloud-6-service-eureka-hystrix-consumer)

Hystrix异常处理

1、我们在调用服务提供者时,服务提供者可能抛出异常,我们自己也可能抛异常,默认情况下方法抛了异常会自动进行服务降级,交给服务降级中的方法去处理;

当我们自己发生异常后,只需要在服务降级方法中添加一个 Throwable 类型的参数就能够获取到抛出的异常的类型

public @ResponseBody Object fallback(Throwable throwable){throwable.printStackTrace();System.out.println(throwable.getMessage());return "/springcloud/eureka/hystrix/goodList 服务降级了";}

2、 如果远程服务有一个异常抛出后我们不希望进入到服务降级方法中去处理,而是直接将异常抛给用户,那么我们可以在@HystrixCommand 注解中添加忽略异常

@HystrixCommand(fallbackMethod = "fallback", ignoreExceptions=Throwable.class)

2、请求限流

Hystrix限流就是限制你某个微服务的使用量(可用线程数、信号量)

Hystrix通过线程池的方式来管理微服务的调用,它默认是一个线程池(大小10个) 管理你的所有微服务,可以给某个微服务开辟新的线程池

@HystrixCommand(fallbackMethod = "fallback",//threadPoolKey 是线程池唯一标识, hystrix 会使用该标识来计数,看线程占用是否超过了, 超过了就会直接降级该次调用threadPoolKey = "goodsService",threadPoolProperties = {//coreSize,线程池核心线程数,默认为10;值为2 那么假设你这个方法调用时间是1s执行完, 那么在1s内如果有超过2个请求进来的话,剩下的请求则全部降级@HystrixProperty(name = "coreSize", value = "2"),//maxQueueSize,线程队列,如果maxQueueSize=-1的话,则该选项不起作用;里面只能放一个请求线程,本来线程数有2个,队列里面允许放一个,那么总共只能有3个请求线程执行,如果超过了就会限流@HystrixProperty(name = "maxQueueSize", value = "1")})@GetMapping(value = "/springcloud/eureka/hystrix/goodLimitList")public @ResponseBody Object getGoodLimitList(){ResponseEntity<Object> responseEntity = restTemplate.getForEntity(GOODS_SERVICE_EUREKA_HYSTRIX_URL, Object.class);return responseEntity.getBody();}

SpringCloud - Spring Cloud Netflix 之 Hystrix熔断器(七)相关推荐

  1. SpringCloud - Spring Cloud Netflix 之 Hystrix ;turbine(十)

    阅读本文前可先参考 SpringCloud - Spring Cloud根/父项目,开发准备(二) https://blog.csdn.net/MinggeQingchun/article/detai ...

  2. SpringCloud - Spring Cloud Netflix 之 Zuul网关;路由(十一)

    阅读本文前可先参考 SpringCloud - Spring Cloud根/父项目,开发准备(二)_MinggeQingchun的博客-CSDN博客 一.API网关 引自百度百科 API网关,软件术语 ...

  3. Spring cloud微服务 Hystrix熔断器

    以下demo代码:https://github.com/wades2/HystrixtDemo 官网定义:Hystrix是一个延迟容错库.在分布式环境中,许多服务依赖项中的一些不可避免地会失败.Hys ...

  4. SpringCloud学习笔记(1)- Spring Cloud Netflix

    文章目录 SpringCloud学习笔记(1)- Spring Cloud Netflix 单体应用存在的问题 Spring Cloud Eureka Eureka Server代码实现 Eureka ...

  5. SpringCloud学习笔记3:Spring Cloud Netflix 组件(五大神兽)

    一.Spring Cloud Netflix有哪些组件? eureka (提供服务注册与发现功能) ribbon(提供负载均衡功能) Feign(整合了ribbon和Hystrix,具有负载均衡和熔断 ...

  6. Spring Cloud Netflix Hystrix

    目录 一. Hystrix 简介 1 什么是灾难性雪崩效应 2 什么是 Hystrix 二. 服务降级 1 修改 application service 代码 2 application client ...

  7. SpringCloud学习笔记(6)----Spring Cloud Netflix之负载均衡-Ribbon的使用

    1. 什么是负载均衡? 负载均衡,就是分发请求流量到不同的服务器. 负载均衡一般分为两种 1. 服务器端负载均衡(nginx) 2. 客户端负载均衡(Ribbon) 2. 服务提供者(spring-c ...

  8. SpringCloud 入门教程(十):和RabbitMQ的整合 -- 消息总线Spring Cloud Netflix Bus

    在本教程第三讲Spring Cloud 入门教程(三): 配置自动刷新中,通过POST方式向客户端发送/refresh请求, 可以让客户端获取到配置的最新变化.但试想一下, 在分布式系统中,如果存在很 ...

  9. spring cloud NetFlix 学习笔记

    spring cloud 1.前言 1.1. 概括 1.2 .常见面试题 2. 微服务概述 2.1 什么是微服务? 2.2 微服务与微服务架构 2.3 微服务优缺点 2.4 微服务技术栈有那些? 2. ...

最新文章

  1. 用Spark和DBSCAN对地理定位数据进行聚类
  2. String : string的长度?string的子串?
  3. MyEclipse使用总结——MyEclipse文件查找技巧
  4. 某些书籍翻译的太屎了,误导人!
  5. Spring 入门学习二之IOC
  6. HttpClient的性能隐患
  7. mysql isolation_mysqltx_isolation
  8. qt 如何 指针 自动 释放内存_要是面试官再问你智能指针的问题,就拿这篇文章“盘他”!!!...
  9. linux cam软件,基于Linux图形交互式线切割CAM软件实现技术研究
  10. FRM-10102错误解决
  11. 初探数据湖(Data Lake),到底有什么用?让我们来一窥究竟...
  12. 中国人民银行 中国银行业监督管理委员会关于印发农村信用社改革试点专项中央银行票据兑付考核办法的通知(银发[2004]253号)
  13. 青云很忙 QingCloud Insight 2017开幕倒计时
  14. 功能测试_测试用例设计方法
  15. Airflow2.2.5任务调度工具
  16. win7 安装超级终端
  17. Q for Mortals2笔记 -- 原子数据类型
  18. 最新学习通JS逆向分析
  19. OGC的WebGIS相关标准
  20. 是否可以将频谱分析仪当做网络分析仪使用?

热门文章

  1. 永磁同步电机学习(二)——svpwm
  2. python怎么在图片上写字_python如何实现内容写在图片上
  3. python 矢量数据融合代码_在ArcGIS下基于Python的矢量数据处理方法
  4. 项目三:爬取视频磁力链接
  5. 机械工业出版社《公司理财》《投资学》《期货、期权及衍生品》错误汇总
  6. 使用Echarts实现圆环图
  7. Echarts基础圆环图
  8. 汉语是思维广阔敏捷的语言
  9. 怎么通过麦克斯韦方程组推导出达朗贝尔方程
  10. The Geodetic Set Problem - POJ 1612 Floyd求最短路径所有点集