微服务容错限流Hystrix入门
为什么需要容错限流
- 复杂分布式系统通常有很多依赖,如果一个应用不能对来自依赖 故障进行隔离,那么应用本身就处在被拖垮的风险中。在一个高流量的网站中,某个单一后端一旦发生延迟,将会在数秒内导致 所有应用资源被耗尽(一个臭鸡蛋影响一篮筐)。
 - 如秒杀、抢购、双十一等场景,在某一时间点会有爆发式的网络流量涌入,如果没有好的网络流量限制,任由流量压到后台服务实例,很有可能造成资源耗尽,服务无法响应,甚至严重的导致应用崩溃。
 
Hystrix是什么
Hystrix 能使你的系统在出现依赖服务失效的时候,通过隔离系统所依赖的服务,防止服务级联失败,同时提供失败回退机制,更优雅地应对失效,并使你的系统能更快地从异常中恢复。
Hystrix能做什么
- 在通过第三方客户端访问(通常是通过网络)依赖服务出现高延迟或者失败时,为系统提供保护和控制
 - 在分布式系统中防止级联失败
 - 快速失败(Fail fast)同时能快速恢复
 - 提供失败回退(Fallback)和优雅的服务降级机制
 - 提供近似实时的监控、报警和运维控制手段
 
Hystrix设计原则
- 防止单个依赖耗尽容器(例如 Tomcat)内所有用户线程
 - 降低系统负载,对无法及时处理的请求快速失败(fail fast)而不是排队
 - 提供失败回退,以在必要时让失效对用户透明化
 - 使用隔离机制(例如『舱壁』/『泳道』模式,熔断器模式等)降低依赖服务对整个系统的影响
 - 针对系统服务的度量、监控和报警,提供优化以满足近似实时性的要求
 - 在 Hystrix 绝大部分需要动态调整配置并快速部署到所有应用方面,提供优化以满足快速恢复的要求
 - 能保护应用不受依赖服务的整个执行过程中失败的影响,而不仅仅是网络请求
 
Hystrix设计思想来源
舱壁隔离模式
货船为了进行防止漏水和火灾的扩散,会将货仓分隔为多个,当发生灾害时,将所在货仓进行隔离就可以降低整艘船的风险。

断路器模式
熔断器就像家里的保险丝,当电流过载了就会跳闸,不过Hystrix的熔断机制相对复杂一些。

熔断器开关由关闭到打开的状态转换是通过当前服务健康状况和设定阈值比较决定的.
- 当熔断器开关关闭时,请求被允许通过熔断器。如果当前健康状况高于设定阈值,开关继续保持关闭。如果当前健康状况低于设定阈值,开关则切换为打开状态。
 - 当熔断器开关打开时,请求被禁止通过。
 - 当熔断器开关处于打开状态,经过一段时间后,熔断器会自动进入半开状态,这时熔断器只允许一个请求通过。当该请求调用成功时,熔断器恢复到关闭状态。若该请求失败,熔断器继续保持打开状态, 接下来的请求被禁止通过。
 
Hystrix工作流程
官网原图

中文版

流程说明
- 每次调用创建一个新的HystrixCommand,把依赖调用封装在run()方法中.
 - 执行execute()/queue做同步或异步调用.
 - 当前调用是否已被缓存,是则直接返回结果,否则进入步骤 4
 - 判断熔断器(circuit-breaker)是否打开,如果打开跳到步骤 8,进行降级策略,如果关闭进入步骤 5
 - 判断线程池/队列/信号量是否跑满,如果跑满进入降级步骤8,否则继续后续步骤 6
 - 调用HystrixCommand的run方法.运行依赖逻辑
 
- 6.1. 调用是否出现异常,否:继续,是进入步骤8,
 - 6.2. 调用是否超时,否:返回调用结果,是进入步骤8
 
- 搜集5、6步骤所有的运行状态(成功, 失败, 拒绝,超时)上报给熔断器,用于统计从而判断熔断器状态
 - getFallback()降级逻辑.四种触发getFallback调用情况(图中步骤8的箭头来源):
返回执行成功结果 
两种资源隔离模式
线程池隔离模式
使用一个线程池来存储当前的请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求堆积入线程池队列。这种方式需要为每个依赖的服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)。
信号量隔离模式
使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,请求来先判断计数器的数值,若超过设置的最大线程个数则丢弃改类型的新请求,若不超过则执行计数操作请求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)。
线程池隔离模式 VS 信号量隔离模式

Hystrix主要配置项


快速上手
pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.netflix.hystrix</groupId>
    <artifactId>hystrix-core</artifactId>
    <version>1.5.12</version>
</dependency>
<dependency>
    <groupId>com.netflix.hystrix</groupId>
    <artifactId>hystrix-metrics-event-stream</artifactId>
    <version>1.5.12</version>
</dependency>
<dependency>
    <groupId>com.netflix.hystrix</groupId>
    <artifactId>hystrix-javanica</artifactId>
    <version>1.5.12</version>
</dependency>
HystrixConfig
@Configuration
public class HystrixConfig {
    /**
     * 声明一个HystrixCommandAspect代理类,现拦截HystrixCommand的功能
     */
    @Bean
    public HystrixCommandAspect hystrixCommandAspect() {
        return new HystrixCommandAspect();
    }
}
HelloService
@Service
public class HelloService {
    @HystrixCommand(fallbackMethod = "helloError",
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
                    @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2")},
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "5"),
                    @HystrixProperty(name = "maximumSize", value = "5"),
                    @HystrixProperty(name = "maxQueueSize", value = "10")
            })
    public String sayHello(String name) {
        try {
            Thread.sleep( 15000 );
            return "Hello " + name + " !";
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
    public String helloError(String name) {
        return "服务器繁忙,请稍后访问~";
    }
}
启动类
@SpringBootApplication
@RestController
public class HystrixSimpleApplication {
    @Autowired
    private HelloService helloService;
    public static void main(String[] args) {
        SpringApplication.run( HystrixSimpleApplication.class, args );
    }
    @GetMapping("/hi")
    public String hi(String name) {
        return helloService.sayHello( name );
    }
}
测试
访问 http://localhost:80809/hi?name=zhangsan
curl -X GET -d 'name=zhangsan' http://localhost:8080/hi
返回
服务器繁忙,请稍后访问~
源码
https://github.com/gf-huanchupk/SpringCloudLearning/tree/master/chapter16
参考
https://github.com/Netflix/Hystrix/wiki
https://blog.51cto.com/snowtiger/2057092
欢迎扫码或微信搜索公众号《程序员果果》关注我,关注有惊喜~

微服务容错限流Hystrix入门的更多相关文章
- 微服务熔断限流Hystrix之流聚合
		
简介 上一篇介绍了 Hystrix Dashboard 监控单体应用的例子,在生产环境中,监控的应用往往是一个集群,我们需要将每个实例的监控信息聚合起来分析,这就用到了 Turbine 工具.Turb ...
 - 微服务熔断限流Hystrix之Dashboard
		
简介 Hystrix Dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard可以直观地看到各Hystrix Command的请求响应时间,请求成功率等数据 ...
 - 微服务组件--限流框架Spring Cloud Hystrix分析
		
Hystrix的介绍 [1]Hystrix是springCloud的组件之一,Hystrix 可以让我们在分布式系统中对服务间的调用进行控制加入一些调用延迟或者依赖故障的容错机制. [2]Hystri ...
 - Hystrix微服务容错处理及回调方法源码分析
		
前言 在 SpringCloud 微服务项目中,我们有了 Eureka 做服务的注册中心,进行服务的注册于发现和服务治理.使得我们可以摒弃硬编码式的 ip:端口 + 映射路径 来发送请求.我们有了 F ...
 - .NetCore微服务Surging新手傻瓜式 入门教程 学习日志---先让程序跑起来(一)
		
原文:.NetCore微服务Surging新手傻瓜式 入门教程 学习日志---先让程序跑起来(一) 写下此文章只为了记录Surging微服务学习过程,并且分享给广大想学习surging的基友,方便广大 ...
 - .NetCore微服务Surging新手傻瓜式 入门教程 学习日志---结构简介(二)
		
原文:.NetCore微服务Surging新手傻瓜式 入门教程 学习日志---结构简介(二) 先上项目解决方案图: 以上可以看出项目结构可以划分为4大块,1是surging的核心底层,2,3,4都可以 ...
 - Go微服务容错与韧性(Service Resilience)
		
Service Resilience是指当服务的的运行环境出现了问题,例如网络故障或服务过载或某些微服务宕机的情况下,程序仍能够提供部分或大部分服务,这时我们就说服务的韧性很强.它是微服务中很重要的一 ...
 - 微服务SpringCloud项目架构搭建入门
		
Spring的微服务框架SpringCloud受到众多公司欢迎,给大家带来一篇框架搭建入门.本次采用的版本是Spring Cloud版本为Finchley.RELEASE. 一.SpringCloud ...
 - 【Spring Cloud】服务容错保护:Hystrix(四)
		
一.雪崩效应 在微服务架构中,由于服务和服务之间可以互相调用,一项工作的完成可能会依赖调用多个微服务模块,但由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就 ...
 
随机推荐
- day07
			
放完了愚人节的假期后就忘记更新了,这样不好,学习的态度也有点懒散了,需要调整过来,这几天在做一个退款流程,想好了建表.逻辑设计和需求分析,然后就是写具体的代码了,有些东西还是要多学习,不然书到用时方恨 ...
 - python!!!!惊了,这世上居然还有这么神奇的东西存在
			
第一次接触到python的时候实在看学习3Blue1Brown的视频线性代数的本质的时候.惊奇的是里面的视频操作,例如向量的变化,线性变换等都是由python用代码打出来的.那时的我只是以为pytho ...
 - 适合Python 新手的5大练手项目,你练了么?
			
接下来就给大家介绍几种适合新手的练手项目. 0.算法系列-排序与查找 Python写swap很方便,就一句话(a, b = b, a),于是写基于比较的排序能短小精悍.刚上手一门新语言练算法最合适不过 ...
 - MySQL varchar类型数据转tinyint类型
			
在mysql数据库中性别字段以前存的是'男'和'女',使用varchar类型存储的,但是在我mongo库中这个字段使用的是'1'和'0'存储的,在两个库之间的数据转换就很不方便,于是想要统一存储类型, ...
 - 计算机协议、标准以及OSI模型的简单介绍
			
由概念启发学习,引导学习.本篇文章中包含了一些最基本的概念和底层知识.虽然零碎,但是这是基础. 一.协议和标准 协议指的是一组控制数据通信的规则.协议有三要素:语法(syntax),语义(semant ...
 - Proxy是在什么时候调用InvocationHandler的invoke方法的
			
最近看到spring的动态代理,扒到深处看到时 Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);看到这一句,顿时比较懵逼,还是 ...
 - QTP自动化测试流程
			
1)准备TestCase - 在进行自动化之前,将测试内容进行文档化,不建议直接录制脚本 - 在录制脚本之前设计好脚本,便于录制过程的流畅 - 由于测试用例设 ...
 - Java NIO Channel通道
			
原文链接:http://tutorials.jenkov.com/java-nio/channels.html Java NIO Channel通道和流非常相似,主要有以下几点区别: 通道可以读也可以 ...
 - ucloud mysql
			
[root@--- bin]# yum install mysql-server Loaded plugins: fastestmirror Setting up Install Process Lo ...
 - SSH概念及常用操作汇总
			
工作有一段时间了,经常用SSH登录远程机器,但对原理一直不是很了解,所以查阅了一些资料,写个小结. 一. SSH是什么? SSH的全称是Secure Shell, 是一种“用来在不安全的网络上安全地运 ...