前言

经过微服务精通之Ribbon原理解析的学习,我们了解到了服务消费者获取服务提供者实例的过程,在这之后,服务消费者会调用服务提供者的接口。但是在调用接口的过程中,我们经常会遇见服务之间的延迟和通信失败的问题,极端情况下,可能会出现因为某个服务性能的下降或者故障宕机,导致服务超时,层层传递,引发雪崩,最终导致整个系统崩溃,而这种情况,我们可以通过熔断器解决这个问题,提高系统的稳定性。


一、熔断器是什么?

顾名思义,熔断器的作用就是将异常的通道关闭,从而保护整个系统。
       例如,有ABCD四个服务,BCD提供服务给A消费,当D因为负载过高或者网络异常导致响应超时时,会导致A对接很多的等待链接,从而导致A也变得异常,以至于其它依赖A的服务也跟着异常,以此类推,从而导致系统大面积的服务瘫痪,如下图。

       这个时候,我们可以在所有服务中加上熔断器,正常情况下,熔断器保持关闭状态,当异常时,则开启熔断器。比如D异常的时候,我们可以把A跟D之间的熔断器打开,就可以避免服务的大面积瘫痪了。

二、Hystrix是什么?

Hystrix是由Netflix开发的,集成到微服务体系里面的一个组件,是微服务体系里面的熔断器。

三、Hystrix原理解析

1.总体流程


流程说明:
       (1)创建Hystrix请求命令;
       (2)执行Hystrix请求命令;
       (3)请求结果是否被缓存,若有缓存,则直接返回;
       (4)熔断器开关是否打开,若打开,则直接执行步骤8;
       (5)信号量或者线程池资源请求,若信号量或者线程池资源已占满,则请求失败,执行步骤8;
       (6)执行请求,若执行失败或者请求超时(默认超时时间为1秒),则直接执行步骤8;
       (7)汇总请求信息,判断是否要打开熔断器开关;
       (8)执行fallback方法,并返回fallback处理结果;
       (9)返回成功响应。

2.请求命令和执行

Hystrix请求采用命令模式,其中,HystrixCommand表示单个操作请求命令,HystrixObservableCommand表示多个操作请求命令。
       HystrixCommand执行:
              execute:同步执行,返回一个单结果对象;
              queue:异步执行,返回一个Future对象,其中包含了一个单结果对象。
       HystrixObservableCommand执行:
              observe:返回observable对象,它代表了多个操作结果,是一个Hot observable;
              toObservable:同样返回observable对象,同样代表多个操作结果,但是它是一个Cold observable。
              注:Hot observable和Cold observable的区别,可通过《RxJava 驯服数据流之 hot & cold Observable》这篇文章了解一下。

3.请求合并

Hystrix支持请求合并,即将一定时间段内对相同依赖服务的请求合并成一个请求。

3.1前提条件

依赖服务必须有一个多参数接口。比如说,有一个根据用户编号查询用户信息的接口,如下图:

       如果要进行请求合并,则依赖服务USER-SERVICE必须提供一个批量查询用户信息的接口,如下图:

3.2 实现方法

在单参数调用方法上面添加注解@HystrixCollapser,多参数调用方法上面添加注解@HystrixCommand,如下图:

       @HystrixCollapser参数说明:
              batchMethod:多参数调用方法名。
              collapserProperties:请求合并参数,timerDelayInMilliseconds表示请求合并时间长度,单位是毫秒;上图配置表示Hystrix会将最近100毫秒的请求合并。

3.3 实现原理

(1)单入参接口配置请求合并以后,Hystrix会对该请求进行拦截,然后将一定时间段内的请求入参合并起来;
       (2)用合并后的请求参数去调用批量处理方法(3.2配置中的batchMethod);
       (3)批量处理方法按照正常的Hystrix请求流程进行处理,得到批量处理结果;
       (4)Hystrix将批量处理结果拆分,并返回给各个单入参接口;
       (5)单入参接口返回结果。

3.4 优缺点

优点:

(1)降低依赖服务请求量,降低其服务压力;
       (2)减少调用依赖服务时的网络消耗;
       (3)减少调用线程池的线程占用。

缺点:

增加了接口的响应时间。

3.5 适用场景

(1)适用于响应时间原本就较长的接口,那合并请求导致的延迟对其几乎无影响;
       (2)适用于并发性能较高,且网络消耗占比较高的接口,那合并请求后,可以减少网络消耗。

4.请求缓存

从Hystrix处理流程中,我们可以知道,Hystrix可以使用缓存来提高接口性能,相关注解如下图:

       注:Hystrix缓存的是同一次请求中相同cachekey的查询结果,当新请求进来时,之前的缓存已失效。

5.熔断器状态

5.1 状态说明

(1)打开状态:该状态下,该接口请求会被拦截,直接进行失败处理;
       (2)关闭状态:该状态下,该接口请求不会被拦截,可以继续后续处理;
       (3)半打开状态:当熔断器打开一段时间后(默认是5秒),Hystrix会允许进行一次接口请求,当请求成功后,关闭熔断器,若请求失败,则再等一段时间后,再进行打开尝试。

5.2 熔断器打开条件

(1)请求总量达到阈值(默认是10秒内20个请求);
       (2)错误率达到阈值(默认是10秒内错误率50%)。

6.信号量与线程隔离

信号量和线程池处理请求的流程如下图:

       线程池流程:当用户请求进来时,熔断器会向线程池请求资源,若请求到资源,则将请求放入线程池中执行,执行完成请求后,再将资源放入线程池;若请求不到资源,则进行降级处理,调用fallback方法。
       信号量流程:当用户请求进来时,熔断器会请求信号量,若请求到信号量,则直接执行请求,执行完成请求后,再释放信号量;若请求不到信号量,则进行降级处理,调用fallback方法。
       两者对比:


四、Hystrix实战

1.Ribbon服务提供者

注:若已看过《微服务精通之Eureka原理解析》,则此章节可跳过。

(1)创建名为service-hi的maven工程

(2)引入Eureka-client依赖

<?xml version="1.0"?>
<projectxsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hxq</groupId><artifactId>spring-cloud-hxq</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>service-hi</artifactId><name>service-hi</name><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

(1)Web依赖:spring-boot-starter-web;
       (2)Eureka-client依赖:spring-cloud-starter-netflix-eureka-client。

(3)创建启动类

package com.hxq;import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** 服务提供者* * @author Administrator**/
@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceHiApplication {public static void main(String[] args) {SpringApplication.run(ServiceHiApplication.class, args);}/*** 服务端口*/@Value("${server.port}")private String port;@RequestMapping("/hi")public String home(@RequestParam(value = "name", defaultValue = "hxq") String name) {return "hi " + name + " ,i am from port:" + port;}
}

启动类要加上@EnableEurekaClient注解。

(4)创建application.yml配置文件

server:port: 9100spring:application:name: service-hieureka:serviceUrl:defaultZone: http://localhost:8761/eureka/

配置说明:
              server.port:Eureka客户端服务端口
              spring.application.name:应用名称,将会显示在Eureka界面的应用名称列。
              eureka.serviceUrl.defaultZone:Eureka服务器的地址,类型为HashMap,缺省的Key为 defaultZone;缺省的Value为 http://localhost:8761/eureka。如果服务注册中心为高可用集群时,多个注册中心地址以逗号分隔。

2.修改Ribbon消费者

注在微服务精通之Ribbon原理解析中的service-ribbon服务的基础上进行修改。

(1)增加Hystrix依赖

<?xml version="1.0"?>
<projectxsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hxq</groupId><artifactId>spring-cloud-hxq</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>service-ribbon</artifactId><name>service-ribbon</name><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency></dependencies>
</project>

新增Hystrix依赖:spring-cloud-starter-netflix-hystrix。

(2)启动类增加Hystrix注解

package com.hxq;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;/*** 服务消费者* * @author Administrator**/
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableHystrix
public class ServiceRibbonApplication {public static void main(String[] args) {SpringApplication.run(ServiceRibbonApplication.class, args);}/*** 负载均衡器* * @return*/@LoadBalanced@BeanRestTemplate restTemplate() {return new RestTemplate();}
}

启动类新增@EnableHystrix注解,以启动Hystrix服务。

(3)修改测试接口

package com.hxq.service.impl;import javax.annotation.Resource;import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;import com.hxq.service.HelloService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;@Service("helloService")
public class HelloServiceImpl implements HelloService {@Resourceprivate RestTemplate restTemplate;@Override@CacheResult(cacheKeyMethod = "getCacheKey")@HystrixCommand(fallbackMethod = "hiError")public String hiService(String name) {return restTemplate.getForObject("http://SERVICE-HI/hi?name={1}", String.class, name);}private String getCacheKey(String name) {return "cache::" + name;}public String hiError(String name) {return "hi," + name + ",sorry,error!";}
}

(1)@CacheResult注解:参考上述“请求缓存”章节,标注此接口使用接口缓存,缓存键值通过getCacheKey方法生成;
       (2)@HystrixCommand注解:参考上述“请求命令和执行”章节,标注此接口是一个单操作的Hystrix接口,接口调用失败后的回调函数为hiError方法。

(4)增加过滤器,初始化Hystrix上下文

注:若不使用请求缓存,可不添加此过滤器。

package com.hxq.filter;import java.io.IOException;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;import org.springframework.stereotype.Component;import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;/*** 设置Hystrix上下文* * @author Administrator**/
@Component
@WebFilter(urlPatterns = "/*", asyncSupported = true)
public class HystrixRequestContextFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 上下文初始化HystrixRequestContext context = HystrixRequestContext.initializeContext();try {chain.doFilter(request, response);} finally {context.close();}}}

3.服务验证

(1)启动service-hi服务

(2)启动service-ribbon服务

(3)调用测试接口

在浏览器中输入http://localhost:9200/hi

请求成功

如下图,可以看到接口返回service-hi服务的数据。

请求失败

如下图,可以看到接口返回回调方法的数据。

五、微服务精通系列文章

  • 微服务精通之Eureka原理解析
  • 微服务精通之Ribbon原理解析
  • 微服务精通之Hystrix原理解析
  • 微服务精通之Feign原理解析

微服务精通之Hystrix原理解析相关推荐

  1. 微服务精通之Feign原理解析

    前言 经过微服务精通之Ribbon原理解析的学习,我们了解到了服务消费者获取服务提供者实例的过程,都是通过RestTemplate来实现的,而且,都是模板化操作.那spring cloud是否有哪个组 ...

  2. 微服务精通之Eureka原理解析

    前言 随着互联网技术的发展,系统用户量的增长,很多系统都采用了分布式的方式进行部署.这个固然大大提高了系统的性能和可用性,但是分布式部署导致各种服务数量大增,这给我们进行服务治理和运维带来了困扰. 一 ...

  3. 【微服务】微服务熔断器--Hystrix

    微服务熔断器--Hystrix 前言 什么是熔断? 什么是降级? 熔断和降级的区别 Hystrix的隔离机制? 什么是Fallback? 熔断器的使用 导入依赖 启动类开启Hystrix配置 声明服务 ...

  4. 微服务架构实施原理详解

    作者:风中程序猿 原文:cnblogs.com/fangfuhai 1 题记 基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发.部署.运维管理.持续开 ...

  5. 推荐:微服务架构的深度解析!

    通过采用微服务架构,企业最大的收益是帮助内部IT建设沿着可演进的方向发展.支持灵活扩展.降低运维成本.快速响应业务变化. 这些底层技术能力的提升让业务更加敏捷.成本可控,企业也可以从中获得技术红利和市 ...

  6. re.containerbase.startinternal 子容器启动失败_微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)...

    走过路过不要错过 点击蓝字关注我们 基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发.部署.运维管理.持续开发持续集成的流程.平台提供基础设施.中间件 ...

  7. 微服务-熔断器Hystrix

    1. 雪崩效应 复杂的分布式体系结构中的应用程序很多都有依赖调用关系, 每个依赖关系有些时候会出现不可避免的失败(异常,超时,网络故障等). 这种多个服务层调用,基础服务的故障可能会导致级联故障,进而 ...

  8. Spring Cloud构建微服务架构-Hystrix断路器

    断路器 断路器模式源于Martin Fowler的Circuit Breaker一文."断路器"本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时," ...

  9. 微服务(项目原理和教程)

    微服务 概述 微服务是一种架构风格 把一个项目拆分成独立的多个服务,多个服务是独立运行,每个服务占用独立进程 Springle Cloud Spring cloud并不是一种技术,是很多技术的总称,很 ...

最新文章

  1. 2018-2019-1 20165234 实验三 并发程序
  2. c语言程序大型案例分析,C语言程序设计习题解析与应用案例分析(第2版)
  3. JS 时间转化为几分钟前 几小时前 几天前
  4. mysql+date+范围+性能_MySQL性能优化的最佳20+条经验
  5. Boost:变量类型boost :: any的单元测试
  6. springcloud----负载均衡--Ribbon与LoadBalance
  7. 【Lucene4.8教程之二】索引
  8. 链表基础概念与经典题目(Leetcode题解-Python语言)
  9. 基于JAVA+Servlet+JSP+MYSQL的在线鲜花商城系统
  10. 关于机器人方面的sci论文_如何给论文润色?从这两个方面入手
  11. 揭秘2017双11背后的网络-双11的网络产品和技术概览
  12. 2021.7.28魔鬼训练报告
  13. 华硕飞行堡垒Fx50j4200H 4600HD 黑苹果High Sierra10.13.6心得
  14. 排列组合Cnm的求法
  15. 微信中控网页授权的实现
  16. 爬虫项目实战二:爬取起点小说网
  17. AIX小型机在DLPAR之间移动磁带机
  18. Linux 日历和计算器命令
  19. ncae的c语言编程高阶怎么考,ncae考试科等目.doc
  20. python游戏开发超级玛丽,100%真实版

热门文章

  1. java 有没有类似于 requests 爬虫_广州地震?用 Python 爬虫带你了解地震
  2. Docker镜像推送到阿里云镜像仓库
  3. 微信小程序居家养老+后台管理系统
  4. android libev 编译,移植libev事件库到Android中
  5. 基于 python 的接口自动化测试,让你轻松掌握接口自动化
  6. 【IoT】创业指南:如何理解需求管理过程?这篇文章就够了
  7. 差速机器人的纯轨迹跟踪仿真(Matlab)
  8. 信号与系统(Python) 学习笔记 (8.1) 离散系统z域分析 -- 系统函数 H(z)
  9. 机器学习基础(一)--基本概念和分类
  10. 一文带您了解软件多租户技术架构