Spring Cloud Netflix - Hystrix
什么是Hystrix
Hystrix是Netflix开源的一款针对分布式系统的延迟和容错库,目的是用来隔离分布式服务故障。它提供线程和信号量隔离,以减少不同服务之间资源竞争带来的相互影响;提供优雅降级机制;提供熔断机制使得服务可以快速失败,而不是一直阻塞等待服务响应,并能从中快速恢复。Hystrix通过这些机制来阻止级联失败并保证系统弹性、可用。
服务熔断
服务提供者(Hystrix)
springcloud-provider-dept-hystrix-8001
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<!--完善监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置
server:
port: 8001
mybatis:
type-aliases-package: cn.pinked.springcloud.pojo
mapper-locations: classpath:mybatis/mapper/*.xml
configuration:
cache-enabled: true
spring:
application:
name: springcloud-provider-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/db01?userUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: 123456
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/ #注册中心地址
instance:
instance-id: provider-dept-hystrix-8001 #Status中的id
#路径/actuator/info页面下的json信息
info:
app: provider1(hystrix)
admin: pinked
#以上与springcloud-provider-dept-8001相同
#以下为hystrix监控配置
management:
endpoints:
web:
exposure:
include: hystrix.stream
控制器controller
@GetMapping("/dept/{id}")
@HystrixCommand(fallbackMethod = "hystrixGet")//当方法失败时, 回调hystrixGet方法
public Dept get(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
if (dept == null) {
throw new RuntimeException("不存在id=>" + id + "的用户");
}
return dept;
}
public Dept hystrixGet(@PathVariable("id") Long id) {
return new Dept().setDnum(id).setDname("id=>" + id + "用户不存在").setDb_source("notFound");
}
启动器
@SpringBootApplication
@EnableEurekaClient //注册到Eureka
@EnableDiscoveryClient //服务发现
@EnableCircuitBreaker //添加熔断机制支持
public class DeptProviderHystrix_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrix_8001.class, args);
}
}
总结
服务提供者在服务异常的情况下,可以将服务请求转发至相应的服务异常处理方法中,以确保整个服务过程不会被阻塞。启动备用的方法,避免报500异常。
服务降级
公共api
springcloud-api
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory {
public DeptClientService create(Throwable throwable) {
return new DeptClientService() {
public List<Dept> queryAll() {
return null;
}
public Dept queryById(Long id) {
return new Dept().setDnum(id).setDname("未找到id=>" + id + ", 服务已关闭").setDb_source("notFount");
}
public boolean addDept(Dept dept) {
return false;
}
};
}
}
手写一个类继承FallbackFactory,从写里面的方法,假设当服务器关闭之后,用户来访问不会报异常而是告诉用户不能用。
@Service
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT", fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@GetMapping("/dept")
List<Dept> queryAll();
@GetMapping("/dept/{id}")
Dept queryById(@PathVariable("id") Long id);
@PostMapping("/dept")
boolean addDept(Dept dept);
}
服务消费者(Feign)
springcloud-consumer-dept-feign
配置
feign:
hystrix:
enabled: true
Dashboard监控
springcloud-consumer-hystrix-dashboard
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
被监控的提供者需要有actuator和hystrix依赖
配置
server:
port: 9001
eureka:
client:
register-with-eureka: false
fetch-registry: false
启动器
@SpringBootApplication
@EnableHystrixDashboard //开启监控
public class DeptConsumerDashboard_9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard_9001.class, args);
}
}
测试