Hystrix 介绍 详解,服务降级,熔断,限流
服务雪崩效应–级联效应
服务雪崩效应:因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过 程,就叫服务雪崩效应
导致雪崩效应的最根本原因是: 大量请求线程同步等待造成的资源耗尽
解决方案
1. 超时机制
2. 服务限流
3. 服务熔断
4. 服务降级
在整个SpringCloud构建微服务的体系中,有一个提供超时机制,限流,熔断,降级最全面 的实现:Hystrix(豪猪) 翻译过来表示:自身带刺,有自我保护的意思,外国人起名字还是 很有意思滴。当然Hystrix并不是Spring的,而是NetFlix公司开源的。那么Spring只是把它 拿过来,在他的基础上面做了一些封装,然后加入到了SpringCloud中,实现高可用的分布 式微服务架构
引入hystrix
@HystrixCommond
@EnableCircuitBreaker
那么Hystrix是怎么做到降级的呢? 他通过一种叫做“命令模式”的方式,继承(HystrixCommand类)来包裹具体的服务调用 逻辑(run方法), 并在命令模式中添加了服务调用失败后的降级逻辑(getFallback),见 (OrderServiceCommand类)
降级(报错,超时)
fallback fallbackMethod,返回静态的信息.备用接口/缓存/mock数据
熔断fusing
重试次数,自动恢复时间,可以再yml中配置的
测试报错和正常的情况,我们可以看到当报错达到一定阈值时,会自动熔断,阈值可以配
置,如下: 一个rolling window内最小的请求数。如果设为20,那么当一个rolling window的时间内(比如说1个rolling window是10秒)收到19个请求,即使19个请求都失败,也不会触发
circuit break。默认20 hystrix.command.default.circuitBreaker.requestVolumeThreshold # 触发短路的时间值,当该值设为5000时,则当触发circuit break后的5000毫秒内都会拒 绝request,也就是5000毫秒后才会关闭circuit。默认5000 hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds
限流
配置线程组 线程池,队列 默认是10个线程
fallback的数据会统计在Metrics中,就是配置熔断的时候使用
用JMeter做压测
@HystrixCommand(fallbackMethod = “findByIdFallback”)
@RestController
public class OrderController {
private static final Logger logger =
LoggerFactory.getLogger(OrderController.class);
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "findByIdFallback")
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
logger.info("================请求用户中心接口==============");
return this.restTemplate.getForObject(
"http://microservice-provider-user/" + id, User.class);
}
public User findByIdFallback(Long id) {
User user = new User();
user.setId(-1L);
user.setName("默认用户");
return user;
}
}
@EnableDiscoveryClient
@SpringBootApplication
@EnableCircuitBreaker
public class ConsumerOrderApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerOrderApplication.class, args);
}
}
降级配置
server:
port: 8010
spring:
application:
name: microservice-consumer-order
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
hystrix:
command:
default:
circuitBreaker:
requestVolumeThreshold: 1
execution:
isolation:
thread:
timeoutInMilliseconds: 4000
UserController
@RestController
public class UserController {
private final Logger logger = Logger.getLogger(getClass());
@Autowired
private UserRepository userRepository;
@Autowired
private Registration registration;
@GetMapping("/{id}")
public User findById(@PathVariable Long id) throws Exception {
logger.info("用户中心接口:查询用户"+ id +"信息");
/*//测试超时触发降级
int sleepTime = new Random().nextInt(2000);
logger.info("sleepTime:" + sleepTime);
Thread.sleep(sleepTime); */
/*//测试熔断,传入不存在的用户id模拟异常情况
if (id == 10) {
throw new NullPointerException();
}*/
//测试限流,线程资源隔离,模拟系统执行速度很慢的情况
// Thread.sleep(3000);
User findOne = userRepository.findOne(id);
return findOne;
}
@GetMapping("/getIpAndPort")
public String findById() {
return registration.getHost() + ":" + registration.getPort();
}
}
熔断配置
server:
port: 8010
spring:
application:
name: microservice-consumer-order
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
hystrix:
command:
default:
circuitBreaker:
requestVolumeThreshold: 3 #次数
sleepWindowInMilliseconds: 10000 #时间
限流,超时模拟
测试限流,线程资源隔离,模拟系统执行速度很慢的情况
Thread.sleep(3000);
server:
port: 8010
spring:
application:
name: microservice-consumer-order
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 20000
配置线程池线程组
参数queueSizeRejectionThreshold 和maxQueueSize 。queueSizeRejectionThreshold默认值是5,允许在队列中的等待的任务数量,超过线程组配置大小的请求直接降级,优先输出,返回结果
@RestController
public class OrderController {
private static final Logger
logger=LoggerFactory.getLogger(OrderController.class);
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "findByIdFallback",
groupKey = "orderUserGroup",
threadPoolKey = "orderUserIdThreadPool",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "2"),
@HystrixProperty(name ="queueSizeRejectionThreshold",
value = "1") })
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
logger.info("==============");
"http://microservice-provider-user/" + id, User.class);
}
public User findByIdFallback(Long id) {
User user = new User();
user.setId(-1L);
user.setName("默认用户");
return user;
}
}
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>