分布式系统环境下,服务间相似依赖很是常见,一个业务调用一般依赖多个基础服务。以下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能致使整个商品服务资源耗尽,没法继续对外提供服务。而且这种不可用可能沿请求调用链向上传递,这种现象被称为雪崩效应。git
针对形成雪崩效应的不一样场景,可使用不一样的应对策略,没有一种通用全部场景的策略,参考以下:github
综上所述,若是一个应用不能对来自依赖的故障进行隔离,那该应用自己就处在被拖垮的风险中。 所以,为了构建稳定、可靠的分布式系统,咱们的服务应当具备自我保护能力,当依赖服务不可用时,当前服务启动自我保护功能,从而避免发生雪崩效应。本文将重点介绍使用Hystrix解决同步等待的雪崩问题。web
在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,经过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix经过隔离服务之间的访问点、中止级联失败和提供回退选项来实现这一点,全部这些均可以提升系统的总体弹性。spring
Hystrix设计目标:后端
Hystrix遵循的设计原则:api
Hystrix如何实现这些设计目标?浏览器
项目仍是用之前的项目,以前在spring-cloud-user写了一个UserController,在里面调用了spring-cloud-service服务,下面把除了spring-cloud-service外的其它服务都开启,而后访问接口会发现报错,看控制台,控制台报的是链接异常,这就是一个典型的通讯失败的案例,在生产过程当中若是访问报一个这个页面老是不那么友好的,那么怎么解决这个通讯失败呢。缓存
为了解决这个问题就引入了hystrix,在服务调用端加入Hystrix包,由于我后面每一个应用都会加入spring-cloud-api这个工程,为了减小后面应用重复导包,我将此包放入spring-cloud-api工程,而且要在调用端加入@EnableCircuitBreaker注解服务器
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
而后就能够对服务进行降级和熔断机制了,在UserController类方法中加入@HystrixCommand(fallbackMethod = "fallback")网络
而后再访问浏览器,发现没啥用,
这正好引出今天问题,怎么触发降级,刚刚配置的方法实际上是回退,降级有三种方案:
熔断的配置信息能够在HystrixCommandProperties类中找到,这里我只写3个
而后再次发起访问,发现发生了熔断
这里有个问题,我这里不演示了,那就是熔断开启以后,后续的正常请求也没法发送过去;说完了这个下面就看下,熔断是如何触发的的,又是怎么恢复的;
1.如何触发熔断?"判断阈值"
10s钟以内,发起了20次请求,失败率超过50%。 熔断的恢复时间(熔断5s)也就是说熔断触发了后,后续请求在5S内都不会发生到服务端 ,这就是熔断的时间窗口说明.
2.熔断会有一个自动恢复。
自支恢复的概念是,5S后请求会自动试着发送到服务端,若是发现发送通讯正常了,熔断就会成为关闭状态
在继续写时要说明一个状况那就是熔断后超时是两个概念,但愿不要搞混了,超时是请求发送中只是时间超了阈值
隔离分为平台隔离、部署隔离、业务隔离、 服务隔离、资源隔离;比喻说项目中的一个case,有一块东西,是要用多线程作一些事情,小伙伴作项目的时候,没有太留神,资源隔离,那块代码,在遇到一些故障的状况下,每一个线程在跑的时候,由于那个bug,直接就死循环了,致使那块东西启动了大量的线程,每一个线程都死循环最终致使系统资源耗尽,崩溃,不工做,不可用,废掉了;在系统中值得咱们隔离的资源无非就几种:CPU、内存、线程
信号量隔离:
/** * 信号量隔离实现 * 不会使用Hystrix管理的线程池处理请求。使用容器(Tomcat)的线程处理请求逻辑。 * 不涉及线程切换,资源调度,上下文的转换等,相对效率高。 * 信号量隔离也会启动熔断机制。若是请求并发数超标,则触发熔断,返回fallback数据。 * commandProperties - 命令配置,HystrixPropertiesManager中的常量或字符串来配置。 * execution.isolation.strategy - 隔离的种类,可选值只有THREAD(线程池隔离)和 SEMAPHORE(信号量隔离)。 * 默认是THREAD线程池隔离。 * 设置信号量隔离后,线程池相关配置失效。 * execution.isolation.semaphore.maxConcurrentRequests - 信号量最大并发数。默认 值是10。常见配置500~1000。 * 若是并发请求超过配置,其余请求进入fallback逻辑。 */ @HystrixCommand(fallbackMethod="semaphoreQuarantineFallback", commandProperties={ @HystrixProperty( name=HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value="SEMAPHORE"), // 信号量隔离 @HystrixProperty( name=HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQU ESTS, value="100") // 信号量最大并发数
线程池隔离
@HystrixCommand(groupKey="spring-cloud-service",
commandKey = "orders",
threadPoolKey="spring-cloud-service",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "30"),//线程池大小
@HystrixProperty(name = "maxQueueSize", value = "100"),//最大队列长度
@HystrixProperty(name = "keepAliveTimeMinutes", value ="2"),//线程存活时间
@HystrixProperty(name = "queueSizeRejectionThreshold", value= "15")//拒绝请求
},
fallbackMethod = "fallback")
前面讲了hystrilx的降级方法,也在以前的篇幅中讲了OpenFeign的应用,下面就以hystrix为基础来说下在OpenFeign中是怎么作到降级的进行对比一下,记得用OpenFeign要开启降级和以前篇幅同样要导入包还有在启动类上加上
@EnableFeignClients(basePackages = "com.ghy.*")注解,另外还要在调用者的配置文件中加入下面的开启配置
#开启feign的支持,触发降级的策略 feign: hystrix: enabled: true
这些搞定后,那就写降级策略了
访问浏览器
若是想在OpenFeign和hystrix同样配置不少信息的话是没办法用注解配置的,只能在配置文件中配置,下面配置下超时的时间配置,在调用端的配置文件中配置
#开启feign的支持,触发降级的策略 feign: hystrix: enabled: true hystrix: command: default: #全局配置, feignclient#method(param) execution: timeout: enable: true #超时的开启 isolation: thread: timeoutInMilliseconds: 3000 #设置超时时间 #设置ribbon的超时时间,并且ribbon的超时时间必定要大于hystrix,这样才能让hystrix生效 ribbon: ReadTimeout: 10000 ConnectTimeout: 10000
下面看下线程池隔离的配置
而后建立一个spring-cloud-hystrix项目进行监控,在spring-cloud-hystrix导入如下包,而后spring-cloud-hystrix的启动类上加上@EnableHystrixDashboard注解
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency>
配置文件以下
server: port: 9095 eureka: instance: hostname: localhost client: serviceUrl: defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/ #指向服务注册中心的地址
访问浏览器登陆到了登陆面板,被监测的服务必定要有下面的包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
而且被监控的对象要配置以下配置以不断获取监控信息
management:
endpoints:
web:
exposure:
include: refresh,hystrix.stream
由于spring-cloud-user服务的端口号是8090,在浏览器上访问 http://localhost:8090/actuator/hystrix.stream能够发如今不停的Ping咱们的服务,其实这面板的做用就是将ping的结果收集而后在面板上展现
在面板上输入要监控的服务信息,若是要监控多个这面板也能作到,要作一个聚合操做
下面有三行数据,左边第一行表示成功数,左边第二行表示熔断数量,左边最后一行表示失败数量
若是有兴趣的朋友能够下个Apache JMeter压测工具压测玩下,我电脑换系统了工具丢了就懒得搞了,这工具也挺简单的