复杂分布式结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败
服务雪崩
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C有调用其他的微服务,这就是所谓的“扇出”;如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上所有资源都在几秒中内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发送更多级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖都不可避免的会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整个服务失败,避免级联故障,以提高分布式系统的弹性。
断路器本身是一种开关装置,当某个服务单元发送故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩
能干嘛
- 服务降级
- 服务熔断
- 服务限流
- 接近实时的监控等
当所有系统的正常时:
当有一个系统出现延迟或异常
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上所有资源都在几秒中内饱和。从而导致整个系统发送更多级联故障
官网地址
熔断机制是对应雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,==进而熔断该节点微服务调用,快速反应错的响应误信息。==当检测到该节点微服务调用响应正常后恢复调用链路。在springcloud框架里熔断机制通过Hystrix实现,Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。
创建一个带有服务熔断的提供者provider-dept-hystrix-8004;把之前8001项目拷贝一份就行,下面我们调整代码
1.4.1 pom添加依赖
ymlorg.springframework.cloud spring-cloud-starter-hystrix 1.4.7.RELEASE
instance:
instance-id: springcloud-provider-hystrix-8004 #修改在Eureka上默认的状态名字
prefer-ip-address: true #true可以显示服务器的ip
controller
在方法上添加@HystrixCommand注解
@RestController
@RequestMapping(value = "/dept")
public class DeptController {
@Autowired
DeptService deptService;
@GetMapping("/findAllDept")
public List findAllDept() {
return deptService.findAllDept();
}
// @GetMapping("/findById/{id}")
// public Dept findById(@PathVariable("id") int id) {
// return deptService.findById(id);
// }
@GetMapping("/findById/{id}")
@HystrixCommand(fallbackMethod = "hystrixFindById") //失败了就会调用备选方案
public Dept findById(@PathVariable("id") int id) {
Dept dept = deptService.findById(id);
if(dept==null){
throw new RuntimeException("id--->"+id+",该信息不存在或无法找到");
}
return dept;
}
public Dept hystrixFindById(@PathVariable("id") int id){
return new Dept().setId(id).setDeptName("id-->"+id+",该信息不存在或无法找到").setDeptSource("No have");
}
@PostMapping("/addDept")
public int addDept(@RequestBody Dept dept) {
return deptService.addDept(dept);
}
}
启动类
@EnableCircuitBreaker //添加对熔断器的支持
@SpringBootApplication
@EnableEurekaClient //在服务启动后自动注册到Eureka中
//@EnableDiscoveryClient //发现服务
@EnableCircuitBreaker //添加对熔断器的支持
public class ProviderHystrixApplication8004 {
public static void main(String[] args) {
SpringApplication.run(ProviderHystrixApplication8004.class, args);
}
}
测试访问
启动项目8004,访问http://localhost:8004/dept/findById/1
访问不存在的id->10
服务降级,当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略降级,以此释放服务器资源以保证核心业务的正常运行
2.2 代码示例服务熔断:针对服务器的,某个服务连接超时或者异常的时候,引起熔断
服务降级:针对客户端,从整体网站请求负载考虑,当某个服务熔断或者关闭时,服务不在被调用,此时客户端,我们可以准备一个FallbackFactory,返回一个默认的值,整体的服务水平下降了,好歹能用,比直接挂掉强
在api工程中的service中创建一个工厂类
DeptClientServiceFallFactory注意 这儿的返回类是DeptClientService这个接口
//服务降级 失败回调
@Component
public class DeptClientServiceFallFactory implements FallbackFactory {
@Override
public DeptClientService create(Throwable throwable) {
return new DeptClientService() {
@Override
public List findAll() {
List list = new ArrayList<>();
Dept dept = new Dept().setId(0).setDeptName("id->"+0+",没有对应的信息,客户端提供了降级信息,这个服务已经关闭了").setDeptSource("服务关了");
list.add(dept);
return list;
}
@Override
public Dept findById(int id) {
return new Dept().setId(id).setDeptName("id->"+id+",没有对应的信息,客户端提供了降级信息,这个服务已经关闭了").setDeptSource("服务关了");
}
@Override
public int addDept(Dept dept) {
return 0;
}
};
}
}
DeptClientService
在客户端配置上面的工厂类
@FeignClient(value = "PROVIDER-DEPT/dept",fallbackFactory = DeptClientServiceFallFactory.class)yml
在feign-8080这个项目中添加开启服务降级
server:
port: 8080
# eureka配置
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka0.com:8000/eureka/,http://eureka1.com:8100/eureka/,http://eureka2.com:8200/eureka/
# 开启服务降级
feign:
hystrix:
enabled: true
即可启动注册中心、启动服务提供者、最后启动消费者测试
关闭服务提供者访问
3 Dashboard流监控总结:
服务熔断: 服务端~ 某个服务超时或者异常,引起熔断;类似保险丝
服务降级: 客户端~ 从整体网站请求负载考虑;当某个服务熔断或者关闭之后,服务不在被调用;此时在客户端我们可以准备一个FallbackFactory,返回一个默认 的值(缺省值),整体的服务水平下降了;但是还是能用,比直接挂掉强。
Hystrix的熔断器监控dashboard; 是用来监控Hystrix的断容器监控的,图形化dashboard是如何实现指标的收集展示的
3.1 代码示例还是一样的为了方便以后查看学习,我们新建一个模块consumer-hystrix-dashborad-8848;我们利用这个工程先搭建一个监控页面
pom添加依赖
ymlorg.springframework.cloud spring-cloud-starter-hystrix-dashboard 1.4.7.RELEASE org.springframework.boot spring-boot-starter-web
server:
port: 8848
hystrix:
dashboard:
proxy-stream-allow-list: "*"
启动类
@SpringBootApplication
@EnableHystrixDashboard //开启监控
public class DeptConsumerDashboard8848 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard8848.class,args);
}
}
启动8848项目,访问页面地址:http://localhost:8848/hystrix
如果出现上述页面,说明我们监控页面搭载完成;
接下来实现监控:
- 监控需要实现熔断的支持在 启动类中开启(@EnableCircuitBreaker //添加对熔断器的支持),我们刚好有一个8004服务提供者项目就直接使用不在创建新项目
- 在修改8004项目添加一个servlet,配合监控
8004项目中添加
@SpringBootApplication
@EnableEurekaClient //在服务启动后自动注册到Eureka中
//@EnableDiscoveryClient //发现服务
@EnableCircuitBreaker //添加对熔断器的支持
public class ProviderHystrixApplication8004 {
public static void main(String[] args) {
SpringApplication.run(ProviderHystrixApplication8004.class, args);
}
//配合监控添加servlet
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
bean.addUrlMappings("/actuator/hystrix.stream");
return bean;
}
}
访问测试
- 启动一个注册中心、启动8848、最后启动8004
- 访问注册中心:http://localhost:8000/确定注册正常
- 访问服务提供者8004:http://localhost:8004/dept/findById/1 确认正常
- 访问数据流地址:http://localhost:8004/actuator/hystrix.stream;出现如下数据地址说明成功
- 填写监控页面信息
- 调用接口测试访问信息(可以尝试错误的访问方式等…)
- 如何监控页面信息
实心圆含义:
1 通过颜色变化代表实例健康程度 绿色<黄色<橙色<红色 递减
2 实心圆大小会根据请求流量变化,流量越大实心圆就越大。所有通过实心圆展示,就可以在大量实例中快速发现故障实例和高压实例。



