一:雪崩效应

如下图所示:A作为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引起了B的不可用,并将不可用像滚雪球一样放大到C和D时,导致整个系统瘫痪,雪崩效应就形成了。

雪崩过程:

1:由于网路或其他原因(硬件故障、程序Bug、用户大量请求)A服务变得不可用,A服务的不可用导致B服务会出现线程的长阻塞,此时如果有大量的请求涌入(用户重试加大流量),B服务servlet容器线程资源会被消耗完毕。大量请求的积压,直接导致B服务变慢,最终瘫痪

2:B服务瘫痪的瘫痪同理会导致C、D服务的瘫痪,最后导致系统瘫痪

二:防雪崩利器

怎么防止雪崩效应的发生呢? 

解决问题方案:对依赖做隔离,Hystrix就是处理依赖隔离的框架,同时也是可以帮我们做依赖服务的治理和监控

依赖隔离分为两种,第一种线程池隔离(Thread-pool Rejection),第二种信号量隔离(semaphre Rejection)

 

 

 

a):线程隔离

首先:容器线程(tomcat、jetty)与   远程服务调用线程隔离,即异步执行服务间远程调用

其次:如果依赖多个微服务,多个依赖间相互隔离

线上建议线程池不要设置过大,否则大量堵塞线程有可能会拖慢服务器。

线程隔离的优点:

可以完全模拟异步调用,方便异步编程。

线程隔离的缺点:

线程开销

线程隔离的适用场景

       不受信服务(第三方接口服务)

有限依赖(依赖的服务不能太多)

NOTE: 

Netflix公司内部认为线程隔离开销足够小,不会造成重大的成本或性能的影响。Netflix 内部API 每天100亿的HystrixCommand依赖请求使用线程隔,每个应用大约40多个线程池,每个线程池大约5-20个线程。

b):信号隔离

信号隔离也可以用于限制并发访问,防止阻塞扩散, 与线程隔离最大不同在于执行依赖代码的线程依然是请求线程(该线程需要通过信号申请),

如果客户端是可信的且可以快速返回,可以使用信号隔离替换线程隔离,降低开销.

信号隔离优点

轻量,无额外开销

信号隔离缺点

不支持异步调用

信号隔离的适用场景

      

        受信服务(公司内部服务)

高依赖(网关)

三:HYSTRIX

a)hystrix简介

所谓的熔断机制和日常生活中见到电路保险丝是非常相似的,当出现了问题之后,保险丝会自动烧断,以保护我们的电器,程序中我们也可以借用这个思想,使用Hystrix实现程序的熔断。

 

hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,这与hystrix本身的功能不谋而合,因此Netflix团队将该框架命名为Hystrix,并使用了对应的卡通形象做作为logo。

b)Hystrix快速体验

Hystrix熔断限流主要埋在客户端,所以只需要在服务消费者方集成Hystrix。集成了Hystrix的客户端,我们一般称为Hystrix客户端

1:pom依赖

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId> spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

2:启动类加@EnableCircuitBreaker

3:fallback逻辑

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.wendao.provider.consumer.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; @RestController
public class ConsumerController { @Autowired
private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "fallback")
@RequestMapping("/findOne")
public User findOne(){
User user = restTemplate.getForObject("http://SPRING-CLOUD-SERVICE-PROVIDER/user/1", User.class); return user;
} //fallback逻辑
private User fallback(){ //TODO ....
return new User("fallback",);
} }

4:测试

关闭服务提供者,测试结果如下:

说明:

1:请求服务提供者失败,怎么样算失败呢?

答:请求超时(默认1秒)算请求失败,不一定是服务提供者没启动,即使服务提供者启动,但是响应慢,超过了超时时间,一样请求失败。

可以通过下面方式设置超时时间

@HystrixCommand(fallbackMethod = "fallback",commandProperties = {
    @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")
})

2:服务提供者请求失败,会调用fallback逻辑,立即给客户端响应,这种情况叫服务降级

四:服务熔断

@RestController
public class ConsumerController { @Autowired
private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "fallback",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value="true"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value=""),
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value=""),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value=""),
})
@RequestMapping("/findOne")
public User findOne(){
//如果熔断器开启是不会进入这个方法的,直接调用fallback逻辑
System.out.println("come in");
User user = restTemplate.getForObject("http://SPRING-CLOUD-SERVICE-PROVIDER/user/1", User.class); return user;
} //fallback逻辑
private User fallback(){ //TODO ....
return new User("fallback",);
} }

刚开始你会发现打印come in ,说明主逻辑方法还是执行了,还是发送了请求,只不过请求失败,执行了fallback逻辑,这个时候只是服务降级。

一旦调用失败次数过大就会导致熔断器开启,熔断器如果open,那么就不可能让你继续执行主逻辑方法了,这时候fallback就成了主逻辑方法

五:熔断器状态机

其实上面演示的不是熔断,熔断器根本没开启,上面演示的只是服务降级。真正的熔断器开启是要满足一定条件【阈值】,才会开启熔断器。

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

请求总数下限:在快照时间窗内,必须满足请求总数下限才有资格根据熔断。默认为20,意味着在10秒内,如果该hystrix命令的调用此时不足20次,即时所有的请求都超时或其他原因失败,断路器都不会打开。

circuitBreaker.requestVolumeThreshold

错误百分比下限:当请求总数在快照时间窗内超过了下限,比如发生了30次调用,如果在这30次调用中,有16次发生了超时异常,也就是超过50%的错误百分比,在默认设定50%下限情况下,这时候就会将断路器打开。

circuitBreaker.errorThresholdPercentage

当熔断器在10秒内发现请求总数超过20,并且错误百分比超过50%,这个时候熔断器打开。打开之后,再有请求调用的时候,将不会调用主逻辑,而是直接调用降级逻辑,通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果。

在断路器打开之后,处理逻辑并没有结束,我们的降级逻辑已经被成了主逻辑,那么原来的主逻辑要如何恢复呢?对于这一问题,hystrix也为我们实现了自动恢复功能。当断路器打开,对主逻辑进行熔断之后,hystrix会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑,当休眠时间窗到期,断路器将进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合,主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时。

六 feign对hystrix的支持

feign只能服务降级,无法进行服务熔断,这个是我个人了解道德

使用方法:

在aplication。properties文件中添加配置:

feign.hystrix.enabled=true

创建熔断类这个类是实现调用服务的那个接口的实现类:

@Component//不能忘记加上该注解
public class UserBizImpl implements IUserbiz {
@Override
public Map update(User user) {
return new HashMap();
} }

再修改feign客户端:

@FeignClient(value="spring-cloud-service-provider",fallback = UserBizImpl.class)

这样就可以了

springcloud微服务总结五 服务熔断的更多相关文章

  1. springcloud微服务总结三 服务客户端

    一 springcloud服务理解: dubbo中服务注册和调用都是都过注解来进行的,dubbo中在service层中调用服务是通过将@service注解改变为dubbo代码架包中的service注解 ...

  2. springcloud组件之hystrix服务熔断,降级,限流

    hystrix 简介 Hystrix是什么 在分布式环境中,许多服务依赖项中的一些必然会失败.Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互.Hystrix通过 ...

  3. springcloud微服务总结二 注册中心

    一:netflix和springcloud关系 netflix公司开源了很多组件,包括服务注册与发现(Netflix Eureka).断路器(Netflix Hystrix).负载均衡(Netflix ...

  4. springcloud微服务总结六

    SpringCloud实战7-Config分布式配置管理 分布式环境下的统一配置框架,已经有不少了,比如百度的disconf,阿里的diamand 官方文档对spring Cloud Config的描 ...

  5. springcloud微服务总结 zuul

    一 springcloud网关组件理解: 为什么需要网关呢? 我们知道我们要进入一个服务本身,很明显我们没有特别好的办法,直接输入IP地址+端口号,我们知道这样的做法很糟糕的,这样的做法大有问题,首先 ...

  6. springcloud微服务总结四 负载均衡

    一:Ribbon简介 Ribbon是Netflix公司开源的一个负载均衡的项目,是一个客户端负载均衡器,运行在客户端上.它是一个经过了云端测试的IPC库,可以很好地控制HTTP和TCP客户端的一些行为 ...

  7. Spring-cloud微服务实战【七】:服务熔断与降级hystrix

      在之前的文章中,我们先后介绍了eureka,ribbon,feign,使用eureka集群的方式来保证注册中心的高可用,在eureka中使用ribbon进行负载均衡,使用feign接口替换手动编码 ...

  8. SpringCloud Netflix (五) : Hystrix 服务熔断和服务降级

    什么是Hystrix 在分布式环境中,许多服务依赖项中的一些服务依赖不可避免地会失败.Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助您控制这些分布式服务之间的交互.Hystrix通过隔离服务 ...

  9. 【五】服务熔断、降级 —— Hystrix(豪猪)

    分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖,每个依赖关系将在某些时候将不可避免地失败. 服务雪崩 多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务 B和微服务 ...

随机推荐

  1. Git的配置和使用帮助

    Git的配置和使用帮助 1.Git的配置 ============== Git有三个地方可以存放配置:系统级配置文件/etc/gitconfig.用户级配置文件~/.gitconfig和仓库级配置文件 ...

  2. oracle级联更新与级联删除

    Oracle级联删除:可以使用外键约束来实现,建立表的主外键关系,给列设置级联删除.如下: ——创建了CLASS表,并设置ID字段为主键. -- Create tablecreate table CL ...

  3. Jquery中extend使用技巧

    在使用Jquery开发的过程中,extend是常用的参数处理函数,特别是对默认值的使用. Jquery的扩展方法原型是: var v=$.extend(dest,src1,src2,[,src3... ...

  4. 13-STL-二分查找

    STL中提供-二分查找算法(binary_search lower_bound upper_bound equal_range   STL包含四种不同的二分查找算法,binary_search    ...

  5. Qt5信号和槽机制

    信号槽是 Qt 框架引以为豪的机制之一.熟练使用和理解信号槽,能够设计出解耦的非常漂亮的程序,有利于增强我们的技术设计能力. 所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被 ...

  6. 2.Hive的几种常见的数据导入方式

    好久没写Hive的那些事了,今天开始写点吧.今天的话题是总结Hive的几种常见的数据导入方式,我总结为四种:(1).从本地文件系统中导入数据到Hive表:(2).从HDFS上导入数据到Hive表:(3 ...

  7. 30.MIN() 函数

    MIN() 函数 MIN 函数返回一列中的最小值.NULL 值不包括在计算中. SQL MIN() 语法 SELECT MIN(column_name) FROM table_name 注释:MIN ...

  8. vue.js的一些模板指令简述

    1.模板指令都是写在<template></template>html里面   v-text : value是什么就显示什么,如果value里面有html的标签,也会直接显示出 ...

  9. Matlab Simulink

  10. 编写高质量代码改善C#程序的157个建议——建议5: 使用int?来确保值类型也可以为null

    建议5: 使用int?来确保值类型也可以为null 基元类型为什么需要为null?考虑两个场景: 1)数据库中一个int字段可以被设置为null.在C#中,值被取出来后,为了将它赋值给int类型,不得 ...