一:雪崩效应
以下图所示:A做为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引发了B的不可用,并将不可用像滚雪球同样放大到C和D时,致使整个系统瘫痪,雪崩效应就造成了。java
雪崩过程:web
1:因为网路或其余缘由(硬件故障、程序Bug、用户大量请求)A服务变得不可用,A服务的不可用致使B服务会出现线程的长阻塞,此时若是有大量的请求涌入(用户重试加大流量),B服务servlet容器线程资源会被消耗完毕。大量请求的积压,直接致使B服务变慢,最终瘫痪spring
2:B服务瘫痪的瘫痪同理会致使C、D服务的瘫痪,最后致使系统瘫痪编程
二:防雪崩利器
怎么防止雪崩效应的发生呢? tomcat
解决问题方案:对依赖作隔离,Hystrix就是处理依赖隔离的框架,同时也是能够帮咱们作依赖服务的治理和监控服务器
依赖隔离分为两种,第一种线程池隔离(Thread-pool Rejection),第二种信号量隔离(semaphre Rejection)并发
a):线程隔离
首先:容器线程(tomcat、jetty)与 远程服务调用线程隔离,即异步执行服务间远程调用 app
其次:若是依赖多个微服务,多个依赖间相互隔离框架
线上建议线程池不要设置过大,不然大量堵塞线程有可能会拖慢服务器。异步
线程隔离的优势:
能够彻底模拟异步调用,方便异步编程。
线程隔离的缺点:
线程开销
线程隔离的适用场景
不受信服务(第三方接口服务)
有限依赖(依赖的服务不能太多)
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",12); } }
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="10"), @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value="10000"), @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value="50"), }) @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",12); } }
刚开始你会发现打印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)
这样就能够了