服务雪崩
1.雪崩过程
- 若存在服务调用链

- 此时Service A流量波动很大,流量经常会突然性增加
- 在这种情况下,就算Service A能扛得住请求,Service B和Service C未必能扛得住这突发的请求

- 若Service C因抗不住请求变得不可用,那么Service B的请求也会阻塞
- 慢慢耗尽Service B的线程资源,Service B就会变得不可用
- 紧接着,Service A也会不可用
2.概念
- 一个服务失败导致整条链路的服务都失败的情形称为服务雪崩
3.雪崩三阶段
硬件故障/程序Bug/缓存击穿/用户大量请求
用户重试/代码逻辑重试
同步等待造成的资源耗尽
4.解决方案
加机器/升级硬件
限流/关闭重试
服务接口拒绝服务/页面拒绝服务/延迟持久化/随机拒绝服务
服务熔断
1.概念
- 当下游服务因某种原因突然变得不可用或响应过慢,上游服务为保证自己整体服务的可用性,不再继续调用目标服务,直接返回,快速释放资源,如果目标服务情况好转则恢复调用
2.解决方案
3.断路器模式
当远程服务被调用时,断路器将监视这个调用,如调用时间太长,断路器将会介入并中断调用。
断路器将监视所有远程资源的调用,如对某个远程资源的调用失败次数足够多,那么断路器会出现并采取快速失败,阻止将来调用失败的远程资源
- 状态图

- 解析
断路器最开始处于closed状态,一旦检测到的错误到达一定数量,断路器便转为open状态(断路器打开);
此时到达reset timeout时间会转移到half open状态;
尝试放行一部分请求到后端,一旦检测成功便回归到closed状态,即恢复服务
阿里的Sentinel
netflix的Hystrix
circuitBreaker.requestVolumeThreshold
circuitBreaker.sleepWindowInMilliseconds
circuitBreaker.errorThresholdPercentage
每当20个请求中,有50%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到5s钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开
服务降级
1.场景
- 当下游服务因某种原因响应过慢,下游服务主动停掉一些不太重要的业务,释放出服务器资源,增加响应速度!
- 当下游服务因某种原因不可用,上游主动调用本地的一些降级逻辑,避免卡顿,迅速返回给用户!
2.服务熔断可视为降级方式的一种
3.实际项目中的降级工作
- 微服务下肯定有很多功能,需要自己区分出主要功能和次要功能(核心业务流程和非核心业务流程),梳理出核心业务流程和非核心业务流程后,在非核心业务流程上加上开关,一旦发现系统扛不住则关掉开关,结束次要流程
- 降低一致性要求,将核心业务流程的同步改异步,强一致性改最终一致性
Hystrix
1.目标
- 微服务架构是高度分布式的,必须防止单个服务(或服务实例)中的问题级联暴露给服务消费者
2.原理图

Hello断路器模式—消费端
2.修改microcloud-api下feign配置
- 目录结构

- pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
@FeignClient(name = "MICROCLOUD-PROVIDER-DEPT", fallbackFactory = DeptFeignServiceFallbackFactory.class)
public interface DeptFeignService {
@RequestMapping("/provider/addDept")
public JsonModel addDept(@RequestBody Dept dept);
@RequestMapping("/provider/findById/{id}")
public JsonModel findById(@PathVariable("id") Long id);
@RequestMapping("/provider/findAll")
public JsonModel fingAll();
}
- 添加DeptFeignServiceFallbackFactory
@Component
public class DeptFeignServiceFallbackFactory implements FallbackFactory<DeptFeignService> {
@Override
public DeptFeignService create(Throwable throwable) {
return new DeptFeignService() {
@Override
public JsonModel addDept(Dept dept) {
JsonModel jsonModel = new JsonModel();
jsonModel.setCode(-1);
jsonModel.setData("消费端端addDept不可用");
return jsonModel;
}
@Override
public JsonModel findById(Long id) {
JsonModel jsonModel = new JsonModel();
jsonModel.setCode(-1);
jsonModel.setData("消费端端findById不可用");
return jsonModel;
}
@Override
public JsonModel fingAll() {
JsonModel jsonModel = new JsonModel();
jsonModel.setCode(-1);
jsonModel.setData("消费端端fingAll不可用");
return jsonModel;
}
};
}
}
3.修改microcloud-consumer-dept-feign-80
- 目录结构

- pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
feign:
hystrix:
enabled: true
Hello后备模式—提供端
1.新建模块microcloud-provider-dept-hystrix-8001
2.目录结构

3.pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
4.修改controller下的DeptProviderServlet
@RestController
@RequestMapping("/provider")
public class DeptProviderServlet {
@Autowired
private DeptService deptService;
@RequestMapping("/findAll")
@HystrixCommand(fallbackMethod = "getMethodCallback")
public JsonModel fingAll(JsonModel jsonModel) {
List<Dept> list = this.deptService.fingAll();
jsonModel.setCode(1);
jsonModel.setData(list);
return jsonModel;
}
public JsonModel getMethodCallback(JsonModel jsonModel) {
jsonModel.setCode(-1);
jsonModel.setData("服务降级,服务查找缓慢");
return jsonModel;
}
}
5.启动类添加注解@EnableCircuitBreaker
@SpringBootApplication
@MapperScan("com.yc.mapper")
@EnableEurekaClient
@EnableCircuitBreaker
public class HystrixProviderApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixProviderApplication.class, args);
}
}
Hello舱壁模式—提供端
1.理论知识
在基于微服务的应用程序中,通常需要调用多个微服务完成一个特定任务。
这些调用默认使用相同线程,该线程是Java容器为处理所有请求预留的
在高服务器请求情况下,一个性能较低的服务会霸占java容器中绝大多数线程,而其它性能正常的服务的请求则需要等待线程资源的释放,导致整个java容器会崩溃
- 问题原理图

- 原理图解析
Hystrix将远程服务请求托管在线程池中
即默认情况下,所有Hystrix命令(@HystrixCommand)共享同一线程池来处理请求
该线程池中持有10个线程来处理各种远程服务请求,可以是REST服务调用、数据库访问等
舱壁模式将远程调用隔离在各个远程调用自己的线程池中,因此单个性能出问题的服务能得到控制,java容器也不会崩溃
- hystrix舱壁模式解决原理图

2.舱壁模式配置
- 新建模块microcloud-provider-dept-hystrix-8001
- pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 修改controller下的DeptProviderServlet
@RestController
@RequestMapping("/provider")
public class DeptProviderServlet {
@Autowired
private DeptService deptService;
@RequestMapping("/findAll")
@HystrixCommand(fallbackMethod = "getMethodCallback",
threadPoolKey = "productGetIdServiceThreadPool",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "10"),
@HystrixProperty(name = "maxQueueSize", value = "10")
}
)
public JsonModel fingAll(JsonModel jsonModel) {
List<Dept> list = this.deptService.fingAll();
jsonModel.setCode(1);
jsonModel.setData(list);
return jsonModel;
}
}
- 启动类添加注解@EnableCircuitBreaker
@SpringBootApplication
@MapperScan("com.yc.mapper")
@EnableEurekaClient
@EnableCircuitBreaker
public class HystrixProviderApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixProviderApplication.class, args);
}
}
HelloDashboard
1.理论知识
- Dashboard 记录 HystrixCommand和HystrixObservableCommand实例在执行过程中的重要信息,对系统运维十分重要
- 信息以 "滚动时间窗"与"桶"结合 的方式进行汇总,并在内存中驻留一段时间,以供内部或外部使用
- 在分布式系统中有很多实例要运维和监控,这样就要开启多个窗口来监控,所以可以利用turbine和dashboard结合来对集群监控
- Hystrix Dashboard

2.Dashboard配置
- 新建Dashboard单独服务模块microcloud-hystrix-dashboard-9001
- 目录结构

- pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
server:
port: 9001 #http://localhost:9001/hystrix
hystrix:
dashboard:
proxy-stream-allow-list: localhost
@SpringBootApplication
@EnableHystrixDashboard
public class DashBoardApp {
public static void main(String[] args) {
SpringApplication.run(DashBoardApp.class,args);
}
}
- 在microcloud-provider-dept-hystrix-8001添加actuator配置,不会去Eureka中看
HelloTurbine
1.理论
- 集群监控端点http://turbine-hostname:port/turbine.stream
- Trubine汇集监控信息并将聚合后的信息提供给Dashboard
- 原理图

2.Turbine配置
- 新建Turbine单独服务模块microcloud-turbine-7777
- pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
server:
port: 7777
eureka: #turbine需要通过eureka获取服务列表,所以需要配置eureka
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka1:7001/eureka/,http://eureka2:7002/eureka/,http://eureka3:7003/eureka/
turbine:
app-config: MICROCLOUD-PROVIDER-DEPT #需要收集信息的服务名(eureka中的服务)
cluster-name-expression: new String("default")
combine-host-port: true #同主机上的服务通过主机名和端口号的组合来进行区分,默认以host来区分
@SpringBootApplication
@EnableTurbine
public class TurbineApp {
public static void main(String[] args) {
SpringApplication.run(TurbineApp.class,args);
}
}