@toc
hystrix能够实现服务降级, 服务容断, 服务限流, 服务隔离.
服务降级: 服务异常, 超时, 熔断, 线程池/信号量打满, 会导致服务降级, 服务降级就是提供另外一个返回信息给调用方, 而不至于一直等待.
服务熔断: 访问量达到最大时, 直接拒绝访问, 并调用服务降级的方法返回友好的提示. 先会进行服务降级, 然后熔断, 然后恢复调用链路. 是应对雪崩效应的一种有效微服务链路保护机制. 在springcloud中服务熔断是通过hystrix实现的, hystrix会监控服务链路的调用情况, 当失败的调用到一定阀值, 缺省值是5秒内20次调用失败, 就会出发熔断机制. 熔断机制的注解是@HystrixCommond
服务限流: 高并发秒杀等场景, 严禁所有请求一拥而上, 排队处理.
雪崩效应:
多个微服务之间调用的时候, 假设A调用B和C, B和C又调用其他的微服务, 就是所谓的"扇出". 如果扇出的链路上某个微服务响应的时间过长或者不可用, 对A服务的资源占用就会越来越多, 进而引起系统崩溃, 就是所谓的雪崩效应.
服务提供者
- 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 超时/异常服务降级
启动类上添加允许Hystrix的注解
@EnableCircuitBreaker
业务类上添加注解
@HystrixCommand(fallbackMethod = "hystrixHander", commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")})
调用的方法
// 这里可以接收到原业务类方法上面的参数
public String hystrixHander(Integer id){
return "方法超时了, 请稍后重试! id= " + id;
}
服务消费者
给某个业务类添加服务降级
- 添加配置
feign:
hystrix:
enabled: true
- 启动类上添加注解
@EnableHystrix
- 业务类上HystrixCommand和服务提供这一样
全局服务降级
上面每个方法都加一个服务降级, 如果方法很多, 就会变得很繁琐, 可以添加全局服务降级.
在类上添加
@DefaultProperties(defaultFallback = "global_fallback")
回调方法
public String global_fallback(){
return "全局服务降级提示";
}
每个方法只需要加上@HystrixCommand即可
就近原则, 如果某个方法需要特殊提示, 还按照原来在方法上的@HystrixCommand注解加上相应属性即可.
但是上面还有一个问题, 就是服务降级的回调方法都写在了业务类中了, 需要和业务类解耦, 需要在FeignClient注解里添加fallback属性, 服务提供者宕机也会触发fallback回调.
@FeignClient(value = "hystrix-payment", fallback = PaymentServiceFallback.class)
package com.mine.service.fallback;
import com.mine.service.PaymentService;
import org.springframework.stereotype.Component;
@Component
public class PaymentServiceFallback implements PaymentService {
@Override
public String ok(Integer id) {
return "fallback 调用ok方法失败了, 哈哈";
}
@Override
public String timeout(Integer id) {
return "fallback 调用timeout方法失败了, 嘿嘿";
}
}
以上都不再依赖@DefaultProperties(defaultFallback = “global_fallback”)和@HystrixCommand, 不过如果有@DefaultProperties注解的话, 还是会优先执行这个注解.
断路器
// 10000毫秒内, 10次请求, 失败率达到60%后跳闸
@HystrixCommand(fallbackMethod = "circuitBreakerFallback", 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") // 失败率达到多少后跳闸
})
public String paymentCircuitBreaker(Integer id){
if(id < 0){
throw new RuntimeException("*******id 不能为负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t调用成功, 流水号:" + serialNumber;
}
public String circuitBreakerFallback(Integer id){
return "id 不能为负数, 请重新尝试!";
}
测试:
页面上访问这个路径, 不停的请求负数, 会调用服务降级的circuitBreakerFallback方法, 后面一段时间内请求整数依然会fallback, 再过一段时间, 才能正常访问, 从closed(正常) -> open(fallback) -> 半open -> closed
hystrix-dashboard
新建项目
- 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
- 启动类上添加注解
@EnableCircuitBreaker
@EnableHystrixDashboard
- 启动后访问地址
http://localhost:10001/hystrix
- 在页面上添加要监控的服务
被监控的服务必须加上spring-boot-starter-actuator
被监控的服务必须加上如下配置
@Bean
public ServletRegistrationBean<HystrixMetricsStreamServlet> servlet(){
HystrixMetricsStreamServlet servlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean<HystrixMetricsStreamServlet> registrationBean = new ServletRegistrationBean<>(servlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
- dashboard页面上添加监控
http://localhost:9005/htstrix.stream
- 如果还是提示不能连接的话, 在dashboard工程中添加配置
hystrix:
dashboard:
proxy-stream-allow-list: "localhost"