- 狂神说Spring Cloud Netflix笔记-01(服务注册与发现)
- 狂神说Spring Cloud Netflix笔记-02(Eureka集群的搭建 )
- 狂神说Spring Cloud Netflix笔记-03(Ribbon负载均衡)
- 狂神说Spring Cloud Netflix笔记-04(Feign负载均衡)
12、Hystrix服务熔断
分布式系统面临的问题
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败!
服务雪崩
什么是Hystrix
官网资料
https://github.com/Netflix/Hystrix/wiki
服务熔断
springcloud-provider-dept-hystrix-8001
创建一个带有服务熔断的服务提供者8001,把之前的8001项目原封不动的拷贝就行,改以下几个位置
pom.xml
添加依赖
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
application.yml
instance:
instance-id: springcloud-provider-dept-hystrix-8001 #修改Eureka上的默认描述信息
prefer-ip-address: true # 为true可以显示服务的ip地址
DeptController
在方法上加入@HystrixCommand即可,这里做一个演示,就写一个方法做测试
//提供Restfull服务!!
@RestController
public class DeptController {
@Autowired
private DeptServiceImpl deptService;
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixGetDept") //失败了就会调用下面的这个备选方案
public Dept getDept(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
if (dept == null) {
throw new RuntimeException("id-->" + id + "不存在该用户,或者信息无法找到");
}
return dept;
}
//备选方案
public Dept hystrixGetDept(@PathVariable("id") Long id) {
return new Dept()
.setDeptno(id)
.setDname("id=>" + id + "没有对应的信息,null---@hystrix")
.setDb_source("not this database in MySQL");
}
}
然后在主启动类上添加对熔断的支持 启用断路器
DeptProviderHystrix_8001
//启动类
@SpringBootApplication
@EnableEurekaClient //在服务启动后自动注册到Eureka中
@EnableCircuitBreaker //添加对熔断的支持 启用断路器
public class DeptProviderHystrix_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrix_8001.class, args);
}
}
启动集群,启动springcloud-provider-dept-hystrix-8001,启动80项目(普通的,不是feign的80项目)
- 访问正常请求http://localhost/consumer/dept/get/1
- 访问不正常请求,http://localhost/consumer/dept/get/10不会显示500错误,而是显示我们备选方案的返回结果
服务降级
服务降级,当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。比如电商平台,在针对618、双11等高峰情形下采用部分服务不出现或者延时出现的情形。
服务熔断:针对服务器的,某个服务连接超时或者异常的时候,引起熔断
服务降级:针对客户端,从整体网站请求负载考虑,当某个服务熔断或则关闭时,服务不在被调用,此时在客户端,我们可以准备一个FallbackFactory,返回一个默认的值,整体的服务水平下降了,好歹能用,比直接挂掉强
在springcloud-api项目的service包下建立DeptClientServiceFallbackFactory
DeptClientServiceFallbackFactory
//服务降级
@Component
//失败回调
public class DeptClientServiceFallbackFactory implements FallbackFactory {
@Override
public DeptClientService create(Throwable throwable) {
return new DeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept()
.setDeptno(id)
.setDname("id=>" + id + ",没有对应的信息,客户端提供了降级的信息,这个服务现在已经被关闭了")
.setDb_source("没有数据");
}
@Override
public boolean addDept(Dept dept) {
//...
return false;
}
@Override
public List<Dept> queryAll() {
//...
return null;
}
};
}
}
然后怎么去体现它呢?还是一样的,在 springcloud-api 项目的DeptClientService接口上添加即可
DeptClientService
失败回调工厂,参数就是上面配置的工厂类,只针对客户端
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT", fallbackFactory = DeptClientServiceFallbackFactory.class)
启动7001项目、启动8001项目(正常的,不是Hystrix的那个)、然后再启动feign的80项目
- 正常访问 http://localhost/consumer/dept/get/1
- 访问一个不存在的数据
- 把8001服务提供者关闭,再次访问http://localhost/consumer/dept/get/1
说明了什么?说明了服务熔断是被动的,服务降级是手动的,但是开启服务降级后,没有关闭服务,访问一个不存在的数据,也会返回一个客户端自定义的返回结果,当把服务关闭后,访问任何请求都是有客户端自定义的结果。
Dashboard流监控
还是老规矩,新建一个项目
springcloud-consumer-hystrix-dashborad
pom.xml
<dependencies>
<!--dashboard监控页面-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
application.yml
server:
port: 9001
hystrix:
dashboard:
proxy-stream-allow-list: "*"
DeptConsumerDashboard_9001
@SpringBootApplication
//服务端必须都要有监控依赖actuator
@EnableHystrixDashboard //开启监控页面 http://localhost:9001/hystrix
public class DeptConsumerDashboard_9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard_9001.class, args);
}
}
然后启动9001项目,直接访问http://localhost:9001/hystrix
现在监控页面搭载完成
我们要如何监控呢?监控什么呢?
我们监控的是实现了熔断支持的类(主启动类上加了@EnableCircuitBreaker注解),这里我们刚好有一个项目springcloud-provider-dept-hystrix-8001,还有一个前提,服务类必须添加actuator依赖
然后我们修改springcloud-provider-dept-hystrix-8001项目的主启动类,添加一个Servlet,为了配合监控使用
DeptProviderHystrix_8001
//启动类
@SpringBootApplication
@EnableEurekaClient //在服务启动后自动注册到Eureka中
@EnableCircuitBreaker //添加对熔断的支持 启用断路器
public class DeptProviderHystrix_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrix_8001.class, args);
}
//为了配合监控使用
//增加一个Servlet
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
}
启动7001项目,启动9001项目,启动hystrix的8001项目,然后访问http://localhost:8001/dept/get/1,有返回数据即可
然后访问http://localhost:8001/actuator/hystrix.stream,会得到一些数据流
然后http://localhost:9001/hystrix,填入以下信息即可