目录
在微服务架构中,如果服务提供者响应缓慢,那么服务消费者的请求就会被强制等待,或响应超时。在高负载场景下,如果不做任何处理,这类问题可能会导致服务消费者资源耗竭甚至整个系统的崩溃。
Hystrix是一个实现了超时机制和断路器模式的工具类库。是由Netflix开源的,用于隔离访问系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。
Hystrix主要通过以下几点实现延迟和容错:
1、包裹请求: 使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用到了设计模式中的“命令模式”。
2、跳闸机制: 当某服务的错误率超过一定阈值时,Hystrix可以自动或手动跳闸,停止请求该服务一段时间 。
3、资源跳闸: Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排除等候,从而加速失败判定。
4、监控: Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等。
5、回退机制: 当请求失败、超时、被拒绝,或当断路器打开,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。
6、自我修复: 断路器打开一段时间后,会自动进行“半开”状态。断路器打开、关闭、半开的逻辑转换。
在Spring Cloud 中整合Hystrix非常方便。我们以前面的服务消费者项目为例进行修改。
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>
在启动类中添加注解 @EnableHystrix
或@EnableCircuitBreaker
,为项目启用断路器支持。
@EnableDiscoveryClient
@EnableHystrix
@SpringBootApplication
public class MicroserviceConsumerMovieRibbonApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(MicroserviceConsumerMovieRibbonApplication.class, args);
}
}
@RestController
public class UserController {
private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@HystrixCommand(fallbackMethod = "findByIdFallback")
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id){
return this.restTemplate.getForObject("http://microservice-provider-user/" + id,User.class);
}
public User findByIdFallback(@PathVariable Long id){
User user = new User();
user.setId(-1L);
user.setName("默认用户");
return user;
}
@GetMapping("/log-user-instance")
public void logUserinstance(){
ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");
UserController.LOGGER.info("{}:{}:{}",serviceInstance.getServiceId(),serviceInstance.getHost(),serviceInstance.getPort());
}
}
在Controller中,我们为findById
方法编写了一个回退方法findByIdFallback
,在findByIdFallback
方法中返回了一个默认用户,在findById
中添加注解@HystrixCommand
在fallbackMethod
属性中指定它的回退方法即可。
修改好上述内容后我们分别启动一个服务提供者,服务消费者与Eureka。访问服务消费者:http://localhost:8011/user/1 可以正常得到数据。当我们把服务提供者关闭后再次访问,会发现返回了之前的默认用户:
。
前面提到Hystrix除了可以实现容错处理,还有监控功能。
使用Hystrix的模块hystrix-metrics-event-stream
,就可以将这些监控信息以文本的形式暴露给外部系统。spring-cloud-starter-netflix-hystrix
已经包含了这个模块,我人只需要添加Actuator,就可以使用/hystrix.stream
端口获得Hystrix监控信息。
只需要在项目中添加Actuator依赖即可。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
重新启动项目,访问 http://localhost:8011/hystrix.stream会出现类似如下图的信息:
上一节我们可以看到监控信息,但都是通过文字形式展示的,不能直观的显示系统状态。
我们可以使用Hystrix Dashboard,让监控数据图形化,可视化。
我们新建一个最简单的Spring Boot 项目
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboardartifactId>
dependency>
@EnableHystrixDashboard
@EnableHystrixDashboard
@SpringBootApplication
public class MicroserviceHystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceHystrixDashboardApplication.class, args);
}
}
server:
port: 8030
上一节我们把要监控的项目的 /hystrix.stream 地址填入Dashboard即可以可视化的监控项目状态。但在微服务中往往有若干个微服务,每个微服务又有多个实例,如果这样一个个监控非常不方便。这一节我们使用Turbine来聚合Hystrix监控数据。
首页我们把服务消费者项目复制一份,修改应用名、端口与方法名
,模拟多个微服务的场景。
这里我把前面使用的服务消费者项目直接复制一份,在配置文件中修改spring.application.name
为microservice-consumer-movie2,修改server.port
为8031。在Controller
中将原方法findById
名更改为findById2
,回退方法名更改为findByIdFallback2
然后新建一个Spring Boot项目
1、依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-turbineartifactId>
dependency>
2、配置文件
server:
port: 8031
spring:
application:
name: microservice-hystrix-turbine
eureka:
client:
service-url:
defaultZone: http://user:admin@localhost:8761/eureka/
instance:
prefer-ip-address: true
turbine:
app-config: microservice-consumer-movie,microservice-consumer-movie2
cluster-name-expression: "'default'"
在配置文件中,把项目注册到Eureka,使用 turbine.app-config
属性添加需要聚合监控的项目名
3、添加注解
在启动类上添加注解 @EnableTurbine
4、聚合监控数据
最后我们启动服务提供者,两个服务消费者,一个Eureka,上一节新建的Dashboard项目与刚新建的Turbine项目。
上一节中我们是把服务消费者的 /hystrix.stream
放入Dashboard中进行可视化,但Turbine项目已经聚合了两个服务消费者的监控数据,因为我们只需要把Turbine项目的地址放入Dashboard中即可。
Turbine项目聚合监控信息的地址为 http://localhost:8031/turbine.stream
点击按钮后可展示如下图的可视化界面
可以看到两个服务消费者的方法都显示出来了,如果同名会显示成一个。
这样我们就完成了监控的聚合,更加方便的显示各各微服务的状态。