15.3 监控失败

15.3 监控失败

每当断路器保护的方法被调用时,它都会收集一些调用相关的数据,并将其发布到一个HTTP流中,这些数据可以实时监控正在运行中的应用的健康状况。在每个断路器收集的数据中,Hystrix流包括如下内容:

  • 方法被调用了多少次;
  • 调用成功了多少次;
  • 后备方法调用了多少次;
  • 方法超时了多少次。

Hystrix流是由Actuator端点提供的。在第16章中,我们会更详细地讨论Actuator,现在只需要将Actuator依赖添加到所有服务的构建文件中,以便于启用Hystrix流即可。在Maven pom.xml文件中,如下的starter依赖会将Actuator添加到项目中:

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

Hystrix流端点会通过“/actuator/hystrix.stream”路径对外暴露。默认情况下,大多数的端点都是禁用的。我们可以通过在每个应用的application.yml文件中添加如下的配置启用Hystrix端点:

1
2
3
4
5
management:
endpoints:
web:
exposure:
include: hystrix.stream

我们还可以将management:endpoints:web:exposure:include属性放到ConfigServer对外提供配置属性的application.yml文件中,这样全局所有的服务就都可以使用它了。

应用启动之后,将会暴露Hystrix流(这个流可以被任意的REST端点消费)。在编写自定义的REST端点之前,我们需要注意HTTP流的每个条目都包含了各种类型的JSON数据,客户端需要大量的工作才能解析这些数据。尽管编写自定义的Hystrix流展现层并非不可能完成的任务,但是在花费大量工夫编写自己的dashboard之前我们可以考虑一下使用Hystrix的dashboard。

15.3.1 Hystrix Dashboard简介

要使用Hystrix Dashboard,我们首先创建一个Spring Boot应用并添加对Hystrixdashboard starter的依赖。如果使用Spring Boot Initializr来创建项目,就可以选择Hystrix Dashboard复选框;否则,我们需要添加如下的<dependency>到项目的Maven pom.xml文件中:

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

项目初始化之后,我们可以通过为主配置类添加@EnableHystrixDashboard注解来启用Hystrix dashboard:

1
2
3
4
5
6
7
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class, args);
}
}

在开发阶段,我们可能会让Hystrix Dashboard与其他服务一起在本地机器运行,还包括Eureka和Config Server。因此,为了避免端口冲突,我们需要为HystrixDashboard选取一个唯一的端口。在Dashboard应用的application.yml文件中,我们可以将server.port设置成任意唯一的值,我通常会将其设置为7979,如下所示:

1
2
server:
port: 7979

现在,我们就可以启动Hystrix Dashboard并查看其效果了。运行之后,打开浏览器并访问http://localhost:7979/hystrix ,我们将会看到如图15.2所示的HystrixDashboard主页。

image-20211023222932777

图15.2 Hystrix Dashboard主页

在Hystrix流监视器中,我们可以设置延迟和标题。延迟的默认值是2秒,指的是轮询周期的间隔,它实际上会延缓流。标题输入域的值会以标题的形式显示在监控页中。对于我们的需求来说,默认值就可以了。

点击Monitor Stream按钮,我们就可以进入Hystrix流的监视器页面了,如图15.3所示。

image-20211023222949317

图15.3 Hystrix流监控页面会显示每个应用的断路器指标

每个断路器都会显示为一个图表并且还带有一些有用的指标数据。图15.3中只显示了getAllIngredients()的断路器,因为到目前为止我们只定义了这一个断路器。

如果看不到断路器的任何图表,只是看到一个单词“Loading”,那么可能是断路器方法都还没有被调用。我们必须向服务发送一个请求,触发断路器保护该方法,这样方法的断路器指标才会显示在Dashboard上。我近距离观察了一个断路器的监视器(见图15.4),并对其中显示的所有数据都进行了标注。

image-20211023223003422

图15.4 每个断路器的监视器都提供了该断路器当前状态的有用信息

在监视器中,最引人注目的是左上角的图表。折线图代表了指定方法过去两分钟的流量,简要显示了该方法的繁忙情况。

折线图的背景是一个大小和颜色会出现波动的圆圈。圆圈的大小表示当前的流量,圆圈越大,流量越大。圆圈的颜色表示它的健康状况:绿色表示健康的断路器,黄色表示偶尔发生故障的断路器,红色表示故障断路器。

在监视器的右上角,以3列的形式显示各种计数器。在最左边的一列中,从上到下,第一个数字(绿色——在本书的电子版中会看出各种颜色)表示当前成功调用的数量,第二个数字(蓝色)表示短路请求的数量,最后一个数字(蓝绿色)表示错误请求的数量。中间一列显示超时请求的数量(黄色)、线程池拒绝的数量(紫色)和失败请求的数量(红色)。第三列显示过去10秒内错误的百分率。

计数器下面有两个数字,代表每秒主机和集群的请求数量。这两个请求率下面是断路器的状态。监视器的底部显示了延迟的中位数和平均值,以及第90、99和99.5百分位的延迟。

15.3.2 理解Hystrix的线程模型

假设某个方法要耗费大量的时间才能完成其任务。这个方法可能向其他的服务发起了HTTP请求,而该服务响应很慢。在服务响应之前,Hystrix会阻塞线程,等待响应。

如果这个方法执行时与调用者在同一个线程上下文中,那么调用者将会一直在这个长时间运行的方法上进行等待。另外,如果被阻塞的线程来自一组数量有限的线程集,比如Tomcat的请求处理线程,而且这种情况一直持续,那么当所有线程耗尽并全部等待响应时,就会影响到可扩展性。

为了避免这种现象,Hystrix会为每项依赖(比如,带有一个或多个Hystrix命令方法的每个Spring bean)指派一个线程池。当Hystrix命令调用时,它将会在来自Hystrix托管的线程池的某个线程中执行,这样会将其与调用者线程隔离开。如果被调用的方法要执行较长时间,就能够允许调用线程不用一直等待,将潜在的线程耗尽隔离在Hystrix托管的线程池中。

你可能会发现在图15.3中除了断路器的监视器外,在页面底部还有另一个监视器,位于“Thread Pools”标题之下。这个区域是Hystrix托管的每个线程池的监视器。图15.5展示了一个线程池监视器,并对其中的数据进行了标注。

image-20211023223028828

图15.5 线程池监视器显示Hystrix托管的线程池的重要统计信息

与断路器的监视器类似,每个线程池监视器在左上角都含有一个圆圈。圆圈的大小和颜色代表了线程池的活跃状态以及它的健康状况。与断路器的监视器不同的是,线程池的监视器没有显示过去几分钟线程池活动的折线图。

右上角显示线程池的名称,其下方是线程池中的线程每秒钟处理请求的数量。线程池监视器的左下角显示如下信息。

  • 活跃线程:当前活跃线程的数量。
  • 排队线程:当前有多少线程在排队。默认情况下,队列功能是禁用的,所以这个值始终为0。
  • 线程池的大小:线程池中有多少线程。

在右下角显示线程池的其他信息:

  • 最大活跃线程:在当前的采样周期中,活跃线程的最大数量。
  • 执行次数:线程池中的线程被调用执行Hystrix命令的次数。
  • 线程队列大小:线程池队列的大小。线程队列功能默认是禁用的,所以这个值没有什么意义。

值得一提的是,作为Hystrix线程池的替代方案,我们可以选择使用信号量隔离(semaphore isolation)。然而,信号量隔离是Hystrix的更高级用法,超出了本章的范围。有关它的更多信息,请参考Hystrix的文档。

现在,我们已经看到了Hystrix dashboard是如何运行的。接下来,我们考虑一下如何处理多个断路器数据流,以及如何将它们聚合到一个流中,以便在Hystrixdashboard中查看。