目录

[TOC]

在微服务架构中,如果服务提供者响应缓慢,那么服务消费者的请求就会被强制等待,或响应超时。在高负载场景下,如果不做任何处理,这类问题可能会导致服务消费者资源耗竭甚至整个系统的崩溃。

Hystrix

Hystrix是一个实现了超时机制和断路器模式的工具类库。是由Netflix开源的,用于隔离访问系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。
Hystrix主要通过以下几点实现延迟和容错:
1、包裹请求: 使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用到了设计模式中的“命令模式”。
2、跳闸机制: 当某服务的错误率超过一定阈值时,Hystrix可以自动或手动跳闸,停止请求该服务一段时间 。
3、资源跳闸: Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排除等候,从而加速失败判定。
4、监控: Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等。
5、回退机制: 当请求失败、超时、被拒绝,或当断路器打开,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。
6、自我修复: 断路器打开一段时间后,会自动进行“半开”状态。断路器打开、关闭、半开的逻辑转换。

整合Hystrix

在Spring Cloud 中整合Hystrix非常方便。我们以前面的服务消费者项目为例进行修改。

添加依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

修改启动类

在启动类中添加注解 @EnableHystrix@EnableCircuitBreaker,为项目启用断路器支持。

1
2
3
4
5
6
7
8
9
10
11
12
13
@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);
}
}

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@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中添加注解@HystrixCommandfallbackMethod 属性中指定它的回退方法即可。

容错测试

修改好上述内容后我们分别启动一个服务提供者,服务消费者与Eureka。访问服务消费者:http://localhost:8011/user/1 可以正常得到数据。当我们把服务提供者关闭后再次访问,会发现返回了之前的默认用户:
默认用户

Hystrix监控

前面提到Hystrix除了可以实现容错处理,还有监控功能。
使用Hystrix的模块hystrix-metrics-event-stream,就可以将这些监控信息以文本的形式暴露给外部系统。spring-cloud-starter-netflix-hystrix已经包含了这个模块,我人只需要添加Actuator,就可以使用/hystrix.stream端口获得Hystrix监控信息。

添加Actuator

只需要在项目中添加Actuator依赖即可。

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

重新启动项目,访问 http://localhost:8011/hystrix.stream会出现类似如下图的信息:
监牢信息

可视化监控数据

上一节我们可以看到监控信息,但都是通过文字形式展示的,不能直观的显示系统状态。
我们可以使用Hystrix Dashboard,让监控数据图形化,可视化。
我们新建一个最简单的Spring Boot 项目

  • 添加以下依赖
    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
  • 启动类添加注解
    在启动类上添加注解 @EnableHystrixDashboard
    1
    2
    3
    4
    5
    6
    7
    8
    @EnableHystrixDashboard
    @SpringBootApplication
    public class MicroserviceHystrixDashboardApplication {

    public static void main(String[] args) {
    SpringApplication.run(MicroserviceHystrixDashboardApplication.class, args);
    }
    }
  • 配置文件
    在配置文件中添加访问端口
    1
    2
    server:
    port: 8030
  • 启动项目
    启动新建的项目:http://localhost:8030/hystrix ,就可以看到Dashboard界面,在中间的地址栏中输入上一节中我们查看监控数据的地址
    Dashboard
    随意填写一个Title 点击按钮,Dashboard即可把http://localhost:8011/hystrix.stream 的文本信息转化成可视化视图:
    可视化监控
    关于显示的指标信息解释可以参考如下图:
    指标解释

Turbine聚合监控数据

上一节我们把要监控的项目的 /hystrix.stream 地址填入Dashboard即可以可视化的监控项目状态。但在微服务中往往有若干个微服务,每个微服务又有多个实例,如果这样一个个监控非常不方便。这一节我们使用Turbine来聚合Hystrix监控数据。
首页我们把服务消费者项目复制一份,修改应用名、端口与方法名,模拟多个微服务的场景。
这里我把前面使用的服务消费者项目直接复制一份,在配置文件中修改spring.application.name为microservice-consumer-movie2,修改server.port为8031。在Controller中将原方法findById 名更改为findById2,回退方法名更改为findByIdFallback2
然后新建一个Spring Boot项目
1、依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>

2、配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
tuebine聚合
点击按钮后可展示如下图的可视化界面
聚合后的可视化界面
可以看到两个服务消费者的方法都显示出来了,如果同名会显示成一个。
这样我们就完成了监控的聚合,更加方便的显示各各微服务的状态。