SpringCloud微服务之四:使用Hystrix实现微服务的容错限流
文章目录
一、雪崩效应
1、雪崩效应概念
- 1、服务雪崩效应是一种因“服务提供者的不可用”(原因)导致“服务调用者不可用”(结果),并将不可用逐渐放大的过程,称之为雪崩效应。
2、雪崩效应形成原因
服务雪崩的过程可以分为三个阶段:
- 服务提供者不可用;
- 硬件故障
- 程序bug
- 缓存击穿
- 用户量大量请求
- 重试加大请求流量;
- 用户重试
- 代码逻辑重试
- 服务调用者不可用;
- 资源耗尽
3、雪崩效应应对策略
- 应用扩容;
- 升级硬件
- 增加机器数量
- 流控;
- 限流
- 关闭重试
- 缓存;
- 缓存预加载
- 服务熔断;
二、如何容错
- 1、为网络请求设置超时。
避免因依赖服务不可用或者网络原因导致响应时间特别长,调用线程/进程无法释放资源,最后导致系统资源被耗尽,最终导致调用服务也不可用。- 2、使用断路器模式。
类似于家里电流过载,会自动跳闸;
如果对某个微服务的请求有大量超时,那么再对这个微服务请求就没有意义啦,可以认为该微服务不可用。这时断路器就会实现快速失败。
断路器也可自动检测依赖的服务是否已经恢复正常。如果恢复正常啦,那么也会恢复请求该服务,通过这种方式实现微服务的“自我修复”;
即当依赖服务不正常时,通过断路器实现快速失败,避免雪崩效应;当依赖服务恢复正常时,又会恢复调用。
三、使用Hystrix实现容错
Hystrix是一个实现超时机制和断路器模式的工具类库。
1、Hystrix简介
Hystrix主要通过以下几点实现对服务的延迟和容错;
- 包裹请求:使用HystrixCommand包裹对依赖的调用逻辑,每个命令都在独立的线程中执行,使用了设计模式中的“命令模式”;
- 跳闸机制:当某服务的错误率超过一定的阈值时,Hystrix可以自动或者手动跳闸,停止请求该服务一段时间;
- 资源隔离:Hystrix为每个依赖都维护了一个小型的线程池。如果该线程池已满,发往该依赖的所有请求都会被立刻拒绝,而不是排队等候,从而加速失败判定;
- 监控:Hystrix可以近乎实时的监控运行指标和配置的变化,例如成功、失败、超时和被拒绝的请求等;
- 回退机制:当请求失败、超时、被拒绝时,或者当断路器打开时,执行回退逻辑。回退逻辑有开发人员自行提供。
- 自我修复:断路器打开一段时间后,进入“半开”状态。之后会调用该服务一个请求,如果成功,则恢复请求;否则,断路器再次打开;
2、整合Hystrix
Edgware.RELEASE的Spring Cloud版本;
- 1、需要引入pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 2、Hystrix断路器开启
Hystrix服务添加@EnableCircuitBreaker或者@EnableHystrix,开启断路器支持
@EnableDiscoveryClient
@SpringBootApplication
@EnableCircuitBreaker
public class ConsumerMovieApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerMovieApplication.class, args);
}
}
- 3、添加控制器
@HystrixCommand(fallbackMethod = “findByIdFallback”)通过注解使该方法具备容错能力;并编写回退方法findByIdFallback,该方法返回值需要与findById的类型一致。
注:因为Hystrix默认的超时时间是1秒,所以第一次用该功能时,无论怎么请求,返回的都是回退方法里默认的值,需要通过application配置修改一下超时时间。
@RestController
public class MovieController {
private static final Logger LOGGER = LoggerFactory.getLogger(MovieController.class);
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "findByIdFallback")
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
User user=this.restTemplate.getForObject("http://microservice-provider-user/" + id, User.class);
return user;
}
public User findByIdFallback(Long id) {
User user = new User();
user.setId(-1L);
user.setName("默认用户");
return user;
}
//可通过Throwable throwable获取对应的错误信息
// public User findByIdFallback(Long id,Throwable throwable) {
// LOGGER.info("进入回退方法:异常"+throwable);
// User user = new User();
// user.setId(-1L);
// user.setName("默认用户"+throwable.getMessage());
// return user;
// }
}
- 4、添加配置
#hystrix超时时间配置 (如果不配置的话默认是1000毫秒超时)
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 30000
- 5、验证
正常请求
断开服务提供者服务,即请求超时,返回的是回退请求中的值
3、Hystrix核心配置
Hystrix核心配置可到该网页查看。
Hystrix本身组件超时设定如下,更多与其他组件配合使用时,Spring Cloud各组件超时总结
#hystrix超时时间配置 (如果不配置的话默认是1000毫秒超时)
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 30000
四、Feign开启Hystrix支持
1、开启
Feign默认不开启Hystrix功能,需要通过添加配置feign.hystrix.enabled=true完成功能开启;
2、指定回退类
很好理解,如下代码:
@FeignClient(name = "microservice-provider-user", fallback = FeignClientFallback.class)
public interface UserFeignClient {
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public User findById(@PathVariable("id") Long id);
}
/**
* 回退类FeignClientFallback需实现Feign Client接口
* FeignClientFallback也可以是public class,没有区别
*/
@Component
class FeignClientFallback implements UserFeignClient {
@Override
public User findById(Long id) {
User user = new User();
user.setId(-1L);
user.setUsername("默认用户");
return user;
}
}
3、指定回退类并输出原因
@FeignClient(name = "microservice-provider-user", fallbackFactory = FeignClientFallbackFactory.class)
public interface UserFeignClient {
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public User findById(@PathVariable("id") Long id);
}
/**
* UserFeignClient的fallbackFactory类,该类需实现FallbackFactory接口,并覆写create方法
*/
@Component
class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
private static final Logger LOGGER = LoggerFactory.getLogger(FeignClientFallbackFactory.class);
@Override
public UserFeignClient create(Throwable cause) {
return new UserFeignClient() {
@Override
public User findById(Long id) {
// 日志最好放在各个fallback方法中,而不要直接放在create方法中。
// 否则在引用启动时,就会打印该日志。
FeignClientFallbackFactory.LOGGER.info("fallback; reason was:", cause);
User user = new User();
user.setId(-1L);
user.setUsername("默认用户");
return user;
}
};
}
}
4、为Feign禁用Hystrix
- 局部禁用
@Component
class FeignDisableHystrixConfiguration{
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder(){
return Feign.builder();
}
@FeignClient(name = "user", configuration = FeignDisableHystrixConfiguration.class)
public interface UserFeignClient {
...
}
- 全局禁用
feign.hystrix.enabled=false
五、Hystrix监控
1、Hystrix监控
引入依赖,通过注解开启Hystrix功能后,通过请求http://localhost:8010/hystrix.stream可以看到不断刷新的监控数据。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、使用Hystrix Dashboard可视化监控
- 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
- 开启功能
启动类添加注解@EnableHystrixDashboard
- 测试
3、使用Turbine聚合监控数据
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
开启Turbine功能:@EnableTurbine
- 主要配置
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
turbine:
appConfig: server-app1,server-app2 #(同样注册在注册中心服务上的应用服务)
clusterNameExpression: "'default'" ## trubine集群名
通过上面的Hystrix Dashboard监控http://ip:port/turbine/stream即达到同时监控多个微服务的情况。
4、使用消息中间件收集数据
微服务应用集群—>MQ(例如rabbitMQ等)—>turbine server–>Hystrix Dashboard
- 被监控Client端
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
连接rabbitMQ
spring:
application:
name: hystrix-mq
rabbitmq:
host: 10.132.XX.XX
port: 5672
username: admin
password: admin
- Turbine服务端
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
server:
port: 8031
spring:
application:
name: turbine
rabbitmq:
host: 10.132.XX.XX
port: 5672
username: admin
password: admin
eureka:
client:
service-url:
defaultZone: http://10.132.33.43:8761/eureka/
instance:
prefer-ip-address: true
在启动的Application中增加 @EnableTurbineStream 注解,即可在启动后自动从queue中搜集监控信息。