一、雪崩效应

“雪崩效应”: 因 '服务提供者' 的不可用导致 '服务调用者' 的不可用,并将不可用逐渐放大的过程

二、Hystrix介绍

Spring Cloud中服务之间的调用方式主要有两种,一种是Ribbon+RestTemplate,一种是Feign声明式服务调用,在实际项目中,为了服务高可用,一个服务通常会集群部署,运行多个实例, 由于网络原因或者服务自身原因,被调用的服务并不能保证100%请求成功,如果这时候有大量的请求请求这个故障的服务,由于服务之间的依赖关系,故障会进行蔓延,这时候会导致调用服务自身也出现不可用的情况,使用Hystrix可以解决这个问题。当某个服务单元发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。

三、准备工作:

本文同样有三个工程,分别是:

eureka-server: 服务注册中心,端口1111;

hystrix-service:服务提供者,端口2222和3333,需要启动多个实例;

ribbon-hystrix: Ribbon服务容错,端口4444

feign-hystrix: Feign服务容错,端口5555

对于eureka-server以及hystrix-service的搭建本文不做详细介绍,需要注意的是hystrix-service需要暴露一个接口/getInfo给外部调用:

/*** @Title: HystrixServiceController* @Description: 服务提供者* @Author WeiShiHuai* @Date 2018/9/11 9:31*/
@RestController
public class HystrixServiceController {private static Logger logger = LoggerFactory.getLogger(HystrixServiceController.class);@Autowiredprivate DiscoveryClient discoveryClient;@RequestMapping("/getInfo")public String getInfo(@RequestParam("name") String name) {ServiceInstance serviceInstance = discoveryClient.getLocalServiceInstance();String host = serviceInstance.getHost();Integer port = serviceInstance.getPort();String info = "hello, name = " + name + ", host = " + host + ", port = " + port;logger.info(info);return info;}}

四、新建springcloud_ribbon_hystrix项目

首先讲一下在Ribbon项目中使用Hystrix断路器的方法:

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"><modelVersion>4.0.0</modelVersion><groupId>com.springcloud.wsh</groupId><artifactId>springcloud_ribbon_hystrix</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>springcloud_ribbon_hystrix</name><description>Spring Cloud Hystrix Ribbon服务单元</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><spring-cloud.version>Camden.SR6</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-hystrix</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-ribbon</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

五、启动类加上@EnableCircuitBreaker注解

该注解主要是打开Hystrix断路器功能

/*** @Description: 应用程序启动类* @Author: WeiShiHuai* @Date: 2018/9/11 9:37* Spring Cloud中服务之间的调用方式主要有两种,一种是Ribbon+RestTemplate,一种是Feign声明式服务调用,在实际项目中,为了服务高可用,一个服务通常会集群部署,运行多个实例,* 由于网络原因或者服务自身原因,被调用的服务并不能保证100%请求成功,如果这时候有大量的请求请求这个故障的服务,由于服务之间的依赖关系,故障会进行蔓延,这时候会导致调用服务自身也出现不可用的情况,使用Hystrix可以解决这个问题* 当某个服务单元发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。* <p>* “雪崩效应”: 因 '服务提供者' 的不可用导致 '服务调用者' 的不可用,并将不可用逐渐放大的过程*/
@SpringBootApplication
@EnableDiscoveryClient
// @EnableHystrix 与 @EnableCircuitBreaker注解用于开启Hystrix断路器功能
//@EnableHystrix
@EnableCircuitBreaker
//@EnableHystrixDashboard注解开启Hystrix仪表盘功能,监控请求情况
//通过Hystrix Dashboard可以直接看到各个Hystrix Command的请求响应时间,请求成功率等数据
@EnableHystrixDashboard
//@SpringCloudApplication = @SpringBootApplication + @EnableDiscoveryClient + @EnableCircuitBreaker
public class SpringcloudRibbonHystrixApplication {public static void main(String[] args) {SpringApplication.run(SpringcloudRibbonHystrixApplication.class, args);}/*** 开启Ribbon负载均衡能力,并注入spring容器*/@Bean@LoadBalancedRestTemplate restTemplate() {return new RestTemplate();}}

六、新建HystrixService

  • 改造原来的服务消费方式,在使用ribbon消费服务的函数上增加@HystrixCommand注解来指定回调方法。
/*** @Title: HystrixService* @ProjectName springcloud_hystrix* @Description: 实现Hystrix断路器* @Author WeiShiHuai* @Date 2018/9/11 9:52*/
@Service
public class HystrixService {private static Logger logger = LoggerFactory.getLogger(HystrixService.class);@AutowiredRestTemplate restTemplate;//@HystrixCommand注解主要对getInfo()开启熔断器的功能,并指定fallbackMethod熔断方法(服务不可用时执行熔断方法)@HystrixCommand(fallbackMethod = "getInfoErrorFallBack")public String getInfo(String name) {String info = restTemplate.getForObject("http://hystrix-service/getInfo?name={name}", String.class, name);logger.info(info);return info;}/*** Hystrix熔断方法(即调用失败回调方法)** @param name* @return*/public String getInfoErrorFallBack(String name) {return "sorry, " + name + ", the hystrix service is not available! ";}}

七、新建HystrixController

注入HystrixService,调用hystrixService.getInfo()接口进行断路器测试:

/*** @Title: HystrixController* @ProjectName springcloud_hystrix* @Description: 测试* @Author WeiShiHuai* @Date 2018/9/11 9:48*/
@RestController
public class HystrixController {private static Logger logger = LoggerFactory.getLogger(HystrixController.class);@Autowiredprivate HystrixService hystrixService;@RequestMapping("/getInfo")public String getInfo(@RequestParam("name") String name) {return hystrixService.getInfo(name);}}

八、启动项目

依次启动eureka-server端口1111、hystrix-service可以启动两个实例2222和3333,ribbon-hystrix端口4444,

浏览器访问http://localhost:4444/getInfo?name=weixiaohuai,如下图:

接口成功调用,同时看后台打印的日志,也实现了服务的负载均衡调用

此时,我们关闭hystrix-service端口分别为2222以及3333的服务,再次访问http://localhost:4444/getInfo?name=weixiaohuai,如下图:

可以看到,当hystrix-service服务不可用时,我们访问其中的接口,执行了我们制定的fallback熔断方法。这样在Ribbon中使用Hystrix断路器功能已经实现。接下来看一下在Feign中使用Hystrix,因为Feign默认集成了Hystrix,因此不需要添加Hystrix的依赖。

九、新建springcloud_feign_hystrix工程

pom.xml只需要引入主要的Feign依赖:

<?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"><modelVersion>4.0.0</modelVersion><groupId>com.sprincloud.wsh</groupId><artifactId>springcloud_feign_hystrix</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>springcloud_feign_hystrix</name><description>Spring Cloud Feign Hystrix</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><spring-cloud.version>Camden.SR6</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-feign</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

十、启动类加上@EnableFeignClients注解

该注解主要是打开Feign远程服务调用的功能

/** * @Description: 应用程序启动类* @Author: WeiShiHuai  * @Date: 2018/9/11 10:23** Feign默认集成了Hystrix,所以只需要加入Feign的依赖即可。* Feign是通过@FeignClient()中指定fallback来实现Hystrix断路器功能的,当远程服务调用失败的时候就会执行这个回调方法。*
*/
@SpringBootApplication
@EnableDiscoveryClient
//开启Feign声明式服务调用功能
@EnableFeignClients
public class SpringcloudFeignHystrixApplication {public static void main(String[] args) {SpringApplication.run(SpringcloudFeignHystrixApplication.class, args);}
}

新建配置文件application.yml:

server:port: 5555
spring:application:name: feign-hystrix
eureka:client:service-url:defaultZone: http://localhost:1111/eureka/

十一、新建Feign接口HystrixFeign

/*** @Title: HystrixFeign* @ProjectName springcloud_hystrix* @Description:* @Author WeiShiHuai* @Date 2018/9/11 10:25*/
@FeignClient(value = "hystrix-service", fallback = HystrixFeignFallback.class)
public interface HystrixFeign {@RequestMapping("/getInfo")String getInfo(@RequestParam("name") String name);}

在feign接口中,我们通过指定fallback来实现Hystrix服务容错功能

新建HystrixFeignFallback回调类,并且实现@FeignClient修饰的接口:

/*** @Title: HystrixFeignFallback* @ProjectName springcloud_feign_hystrix* @Description: FeignClient失败回调方法* @Author WeiShiHuai* @Date 2018/9/11 10:28* FeignClient失败回调方法必须实现使用@FeignClient标识的接口(implements HystrixFeign),实现其中的方法*/
@Component
public class HystrixFeignFallback implements HystrixFeign {/*** 由于某种原因使得服务调用不成功时会执行该回调方法** @param name* @return*/@Overridepublic String getInfo(String name) {return "sorry " + name + ", feign client error";}}

十二、新建FeignHystrixController

暴露一个getInfo接口给外部调用,如下:

/*** @Title: HystrixFeignController* @ProjectName springcloud_feign_hystrix* @Description: 测试Feign* @Author WeiShiHuai* @Date 2018/9/11 10:28* 注入FeignClient,调用feignClient的方法实现远程方法调用*/
@RestController
public class HystrixFeignController {private static Logger logger = LoggerFactory.getLogger(HystrixFeignController.class);@Autowiredprivate HystrixFeign hystrixFeign;/*** 使用http://localhost:5555/getInfo?name=xxx访问,实际上会通过FeignClient调用服务hystrix-service提供的getInfo接口** @param name* @return*/@GetMapping("/getInfo")public String getInfo(@RequestParam("name") String name) {String info = hystrixFeign.getInfo(name);logger.info(info);return info;}}

接下来,同样启动eureka-server、以及hystrix-service两个实例,还有启动feign-hystrix,访问http://localhost:5555/getInfo?name=weixiaohuai,结果如下:

接口已经成功调用,通过查看后台日志,同样feign也实现对服务的负载均衡调用

此时,我们停掉hystrix-service的两个实例,再次访问http://localhost:5555/getInfo?name=weixiaohuai,服务会进行熔断处理,执行了我们指定的fallback方法。

由此证明Hystrix断路器起作用了。

十三、总结

雪崩效应的原因:
1) 服务提供者不可用
 a.硬件故障
 b.程序Bug
 c.用户大量请求:在秒杀和大促开始前,如果准备不充分,用户发起大量请求造成服务提供者的不可用
2) 重试加大流量
 a.用户重试:用户由于忍受不了界面上长时间的等待,而不断刷新页面甚至提交表单
 b.代码逻辑重试:服务调用端的会存在大量服务异常后的重试逻辑
3) 服务调用者不可用
 a.同步等待造成的资源耗尽:使用 同步调用 时, 会产生大量的等待线程占用系统资源. 一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态, 造成服务雪崩效应产生

雪崩效应的解决措施:
1) 流量控制
 a.网关限流
 因为Nginx的高性能, 目前一线互联网公司大量采用Nginx+Lua的网关进行流量控制, 由此而来的OpenResty也越来越热门.
 b.用户交互限流
 具体措施:
 a. 采用加载动画,提高用户的忍耐等待时间.
 b. 提交按钮添加强制等待时间机制.
c.关闭重试
2) 改进缓存模式
 a.缓存预加载
 b.同步改为异步刷新
3) 服务自动扩容
a.AWS的auto scaling
4) 服务调用者降级服务
 a.资源隔离:主要是对调用服务的线程池进行隔离.
 b.对依赖服务进行分类
 依赖服务分为: 强依赖和若依赖. 强依赖服务不可用会导致当前业务中止,而弱依赖服务的不可用不会导致当前业务的中止.
 c.不可用服务的调用快速失败
一般通过 超时机制, 熔断器 和熔断后的 降级方法 来实现。

Spring Cloud Hystrix服务容错 (学习总结)相关推荐

  1. Spring Cloud Hystrix 服务容错保护

    在微服务架构中,我们将系统拆分成了很多服务单元,各单元的应用间通过服务注册与订阅的方式互相依赖.由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身间 ...

  2. Spring Cloud微服务简介

    1. 基础知识1 什么是微服务架构? 与单体系统的区别 如何实施微服务? 微服务优缺点 为什么选择Spring Cloud? 微服务技术选型 为什么选择Spring Cloud? Spring Clo ...

  3. hystrix 源码 线程池隔离_Spring Cloud Hystrix 源码学习合集

    # Spring Cloud Hystrix 源码学习合集 **Hystrix: Latency and Fault Tolerance for Distributed Systems** ![](h ...

  4. Spring Cloud之Hystrix服务容错

    Spring Cloud之Hystrix服务容错 Hystrix的概述 Hystrix的使用 相关依赖 Eureka注册中心 服务提供者 服务消费者 执行测试 @HystrixCommand详解 服务 ...

  5. Spring Cloud 学习笔记(四)-Spring Cloud Hystrix

    Spring Cloud 学习笔记(四)-Spring Cloud Hystrix 由于前一阵子项目的原因,今天才继续弄上,今天想学习一下Hystrix组件 这个组件还挺抽象的,最开始我一直没太明白, ...

  6. 硬核!从0到1学习Spring Cloud微服务章节《建议收藏》

    为什么要使用学习springcloud以及他的优势? Spring Cloud 来源于 Spring,质量.稳定性.持续性都可以得到保证. spirng Cloud 天然支持 Spring Boot, ...

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

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

  8. 实战系列-Spring Cloud微服务中三把利器Feign、Hystrix、Ribbon

    导语   在之前的分享中分享过关于Fegin的底层实现原理,以及Spring Cloud OpenFegin的启动原理.在这次的分享中主要总结一下Spring Cloud 微服务架构的三把利器.对于F ...

  9. spring cloud微服务治理eureka、hystrix、zuul代码例子

    spring cloud微服务中台服务代码例子,包括eureka.hystrix.zuul https://github.com/birdstudiocn/spring-cloud-sample/tr ...

  10. spring cloud微服务分布式云架构 - Spring Cloud集成项目简介

    Spring Cloud集成项目有很多,下面我们列举一下和Spring Cloud相关的优秀项目,我们的企业架构中用到了很多的优秀项目,说白了,也是站在巨人的肩膀上去整合的.在学习Spring Clo ...

最新文章

  1. Java mission control 飞行记录器开启失败
  2. APUE读书笔记 之 进程关系
  3. ubuntu 14.04 no valid active connections found
  4. T-SQL、Jet SQL、PL-SQL
  5. 专利:结构化大数据通信协议
  6. HTML day02
  7. Linux运维人员成长之路学习书籍推荐(未删减版)
  8. uniapp引入字体包——DIN
  9. SQL 常见面试题解析
  10. 无人机系统测试软件,无人机航测软件(pix4D)
  11. 什么是SVG及使用方式
  12. 读“技术的执念”有感
  13. java:io的基本实例
  14. c语言代码大全复制,垃圾回收算法实现之 - 复制算法(完整可运行C语言代码)...
  15. github whs_从iPhone或iPod Touch获得WHS的基本访问权限,而无需安装应用程序
  16. android mux协议,协议细节 - Mux.Cool - 《Project V(V2RAY)文档手册》 - 书栈网 · BookStack...
  17. 【梯度消失和梯度爆炸问题详解】
  18. 学c语言的第一篇博客~
  19. java form的时间格式_java date日期格式
  20. Fabric 搭建测试网络并部署智能合约

热门文章

  1. 阿里云云计算 50 云监控的使用
  2. 算法:Gray Code 格雷码
  3. mysql数据库怎容器化_数据库部署是否合适容器化?
  4. Linux中MySQL没有schema_linux服务器安装Mysql后,只能看到information_schema/test这两个库,无法修改密码...
  5. N!阶层末尾有多少0
  6. 深度学习框架PyTorch:入门与实践 学习(二)
  7. python模拟登录的实现
  8. 机器学习,参数之-学习率设置
  9. 计算机操作系统详细学习笔记(四):设备管理 —— I/O 管理
  10. 【BZOJ 1103】大都市【dfs序上建立树状数组、维护路径前缀和】