复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。
服务雪崩扇出
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”.
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
所以,
通常当你发现一个模块下的某个实例失败后,这时候这个模块依然还会接收流量,然后这个有问题的模块还调用了其他的模块,这样就会发生级联故障,或者叫雪崩。
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩
服务降级 环境搭建在服务提供者的控制器方法中特意出现异常,超时异常,算数异常等
一个测试工具Jmeter:模拟大量的请求访问
引入依赖
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
在yaml和主程序
@SpringBootApplication
@EnableDiscoveryClient
//表示开启服务的断路器
@EnableCircuitBreaker
public class consulProvider {
public static void main(String[] args) {
SpringApplication.run(consulProvider.class,args);
}
}
查看控制器类
@RestController
public class consulWeb {
@Value("${server.port}")
private String serverport;
// 指定服务降级(当服务出现异常,调用一个应急方案)
// commandProperties指定最大超时时间
@HystrixCommand(fallbackMethod = "consulException", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
})
@RequestMapping("/consul/pro")
public String consulWp() {
// 这里是为了延迟运行时间
// int a = 10/0;
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "服务提供者" + serverport;
}
public String consulException() {
return "/consul/pro的异常处理";
}
}
查看访问结果
所以在服务的消费者中一样可以使用服务降级来进行设置应急方案 全局服务降级有的时候我们不需要每一个服务方法都去指定一个,应急方法,使用一个公用的
没有指定应急方法的就使用公用的
@DefaultProperties(defaultFallback="")
操作 主要都是在控制器类中@RestController
//这里指定默认的全局的应急方案
@DefaultProperties(defaultFallback = "quanju")
public class ConsummerWeb {
// 使用restTemplate进行消费者调用提供者
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/consummconsul")
// 如果指定自定义应急方案,就使用自己的否则使用默认的
@HystrixCommand
public String consummershow() {
int a = 10/0;
String forObject = restTemplate.getForObject("http://provider/consul/pro", String.class);
System.out.println(forObject);
return "success" + forObject;
}
// 下面是通过feign进行的操作
// 引入feign接口,因为在feign接口中就已经调用了服务提供者
@Autowired
private feignProvider feignProvider;
// 使用服务降价 指定一个应急方法
@HystrixCommand(fallbackMethod = "cosummerException")
@RequestMapping("/feignConsumm")
public String consummershow01() {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
String s = feignProvider.consulWp();
return "success02" + s;
}
// 自定义的应急方法
public String cosummerException(){
return "feignConsumm的异常处理";
}
// 全局应急方法
public String quanju(){
return "全局";
}
}
消费者服务降级
我们可以通过@HystrixCommand进行服务降级,但是调用提供者和消费者本身业务存放在一起了。
我们接下来可以通过Feign接口的服务降级方式区别开来,当服务调用失败或者服务调用挂掉
步骤 展示接口实现类//实现接口,重写方法,返回feign接口的实现类 @Component public class feignProviderImple implements FallbackFactory展示接口{ @Override public feignProvider create(Throwable throwable) { // 返回一个实现类 return new feignProvider() { // 重写方法 @Override public String consulWp() { return "feign实现类的服务降级"; } }; } }
//在接口中指定降级的实现类
@FeignClient(value = "provider",fallbackFactory = feignProviderImple.class)
public interface feignProvider {
@RequestMapping("/consul/pro")
public String consulWp();
//cn/service/feignProvider.java
}
yaml配置
feign:
hystrix:
enabled: true
查看结果
这个消费者不会出现异常,查看提供者出现异常的情况
// 使用服务降价 指定一个应急方法
@HystrixCommand(fallbackMethod = "cosummerException")
@RequestMapping("/feignConsumm")
public String consummershow01() {
String s = feignProvider.consulWp();
System.out.println(s);
return "success02" + s;
}
正常调用的时候,因为服务调用者还在,出现异常展示了服务调用者的异常应急方案
关闭服务调用者,观察结果
注意 服务熔断 熔断机制概述熔断机制是应对雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务出错不可用或者响应时间太长时,
会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。
当检测到该节点微服务调用响应正常后,恢复调用链路。
当一个服务调用出现错误,会直接进行服务的降级。当错误概率过高开启断路器。即使成功的服务也会调用服务降级
当成功的概率提高了,开始恢复调用链路
在Spring Cloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,
当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是@HystrixCommand。
//=========服务熔断
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_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 = "60"), //表示失败率达到多少开启
})
查看我的服务消费者
@HystrixCommand(fallbackMethod = "cosummerException", commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
//表示开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
//表示请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
// 表示时间窗口期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),
//表示失败率达到多少开启
})
@RequestMapping("/feignConsumm/{id}")
public String consummershow01(@PathVariable("id") int id) {
if(id>5){
int i = 10/0;
}
String s = feignProvider.consulWp();
System.out.println(s);
return "success02" + s;
}
// 自定义的应急方法
public String cosummerException(@PathVariable("id") int id) {
return "feignConsumm的异常处理";
}
查看结果
刚开始运行错误的,在运行正确的,但是正确的也显示错误的。
随着正确率提示,服务链路恢复
这里要注意,应急方案的方法,要与服务访问的方法的格式一致。
比如传入的参数等配置信息
服务熔断类型 马丁弗勒:服务熔断笔记图 服务监控 监控服务端搭建重新创建一个SpringBoot微服务项目,用来开启DashBoard监控
导入依赖
//两个主要的依赖
org.springframework.cloud
spring-cloud-starter-hystrix
1.4.6.RELEASE
org.springframework.cloud
spring-cloud-starter-hystrix-dashboard
1.4.6.RELEASE
//用来表示是SpringBoot
org.springframework.boot
spring-boot-starter-web
yml不需要设置内容
server: port: 9001主程序
@SpringBootApplication
@EnableHystrixDashboard //开启监控依赖
public class HystrixActour {
public static void main(String[] args) {
SpringApplication.run(HystrixActour.class,args);
}
}
展示结果
服务客户端部署
上面搭建了一个监控,想要准确监控一个服务还需要再服务中编写内容
引入依赖// 这两个是主要的依赖
org.springframework.cloud
spring-cloud-starter-hystrix
1.4.6.RELEASE
org.springframework.boot
spring-boot-starter-actuator
yml,不需要改动
主程序
再主程序中引入@Bean来指定监控页面
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker //这个注解添加对服务熔断的支持
public class ProviderHello {
public static void main(String[] args) {
SpringApplication.run(ProviderHello.class,args);
}
// 这是监控的重点
//增加一个 Servlet
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
//访问该页面就是监控页面
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
}
展示结果
直接查看监控页面
通过HystrixDashBoard访问监控页面
这个监控页面会根据服务的请求来展示数据
监控页面数据


