微服务架构中,服务数量大大增加,调用关系变得复杂。用户的一个请求,会放大为内部服务间的若干次调用,依赖实际上变多了。而一个服务的故障,沿着调用链传播,也可能造成难以预料的影响。更糟糕的是,在服务数量很多的时候,故障是无可避免的。不论单个服务可用性达到几个 9,在服务数量 N 很大时,它的乘方一定会离 0 越来越近。在这种现状下,增强整体容错性就成为一项重要的工作。
一方面当下游服务挂掉时,上游服务作为调用方,需要有一定容错能力,设置一些兜底逻辑,尽量避免直接随之也挂掉。同时,也应避免无脑多次重试,降低下游服务的负载,使其有恢复的机会。
另一方面,作为服务本身,其资源是有限的,服务能力也是有上限的。对于超出上限的流量,只能忍痛丢弃。毕竟只服务部分请求,总比接收所有请求然后拖死整个系统要好得多
这两方面的考量,正是我们稳定性平台的主题:熔断与限流。 网络上流传着一句话,熔断、限流、降级是分布式架构的三板斧,可见其重要性。
1、Hystrix能做什么
通过hystrix可以解决雪崩效应问题,它提供了资源隔离、降级机制、融断、缓存等功能。
**资源隔离:**包括线程池隔离和信号量隔离,限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其他服务调用。
**降级机制:**超时降级、资源不足时(线程或信号量)降级,降级后可以配合降级接口返回托底数据。
**融断:**当失败率达到阀值自动触发降级(如因网络故障/超时造成的失败率高),熔断器触发的快速失败会进行快速恢复。
**缓存:**返回结果缓存,后续请求可以直接走缓存。
**请求合并:**可以实现将一段时间内的请求(一般是对同一个接口的请求)合并,然后只对服务提供者发送一次请求。
2、两种隔离模式
-
线程池隔离:
使用一个线程池来存储当前请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求先入线程池队列。这种方式要为每个依赖服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)
-
信号量隔离:
使用一个原子计数器(或信号量)记录当前有多少个线程在运行,请求来先判断计数器的数值,若超过设置的最大线程个数则丢弃该类型的新请求,若不超过则执行计数操作请求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)
3、三种降级模式
**快速模式:**服务调用失败立刻返回
**故障转移:**服务调用失败则调用备用服务,备用服务调用失败则调用下一级备用服务,比如服务提供者不响应,则从缓存中取默认数据 。
**主次模式:**比如,开发中需要上线一个新功能,但为了防止新功能上线失败可以回退到老的代码,我们会做一个开关,比如一个配置开关,可以动态切换到老代码功能。那么Hystrix它是使用通过一个配置来在两个command中进行切换。
4、整体请求流程图
下图显示了通过Hystrix向服务依赖项请求时发生的情况:
-
此流程整体说明:
1、构造一个HystrixCommand或HystrixObservableCommand对象 2、执行命令 3、响应是否已缓存? 4、电路开路了吗? 5、线程池/队列/信号量是否已满? 6、HystrixObservableCommand.construct() 要么 HystrixCommand.run() 7、计算电路健康 8、获取Fallback 9、返回成功的回应
下面为通过Hystrix向服务依赖项请求的流程图:
标签:降级,调用,服务,请求,Hystrix,Spring,缓存,线程,Cloud From: https://blog.51cto.com/u_11906056/7011749