使用Spring Boot Actuator将指标导出到InfluxDB和Prometheus

使用Spring Boot Actuator将指标导出到InfluxDB和Prometheusmysql

 

Spring Boot Actuator是Spring Boot 2发布后修改最多的项目之一。它通过了主要的改进,旨在简化定制,并包括一些新功能,如支持其余Web技术,例如新的反应模块 - 。它还为 添加了开箱即用的支持,这是一个开源时间序列数据库,旨在处理大量带时间戳的数据。与 使用的版本相比,它其实是一个很大的简化。您能够经过阅读我以前的一篇文章使用Grafana和InfluxDB自定义指标可视化来了解本身有多少。我在那里描述了如何使用 bean将[Spring Boot Actuator生成的指标导出到InfluxDB。示例Spring Boot应用程序已在分支主文件中的GitHub存储库sample-spring-graphite上提供该文章。对于本文,我建立了分支spring2,它展现了如何实现与使用Spring Boot 2.0版本以前相同的功能。弹簧启动执行器。web

另外,我将向您展现如何将相同的指标导出到另外一个流行的监控系统,以便有效地存储时间序列数据 - 。在 和 之间导出指标的模型之间存在一个主要区别。第一个是基于推送的系统,而第二个是基于拉的系统。所以,咱们的示例应用程序须要主动将数据发送到 监控系统,而使用 时,它只须要公开将按期获取数据的端点。让咱们从 开始吧。spring

运行InfluxDBsql

在上一篇文章中,我没有写太多关于这个数据库及其配置的内容。因此,如今我说一些关于它的话。第一步是个人示例的典型步骤 - 咱们将使用 运行 容器。这是在本地计算机上运行 并在 端口上公开 的最简单命令。docker

一旦咱们启动了该容器,您可能但愿在那里登陆并执行一些命令。没有比这更简单的了,只需运行如下命令便可。登陆后,您应该看到目标Docker容器上运行的InfluxDB版本。shell

 

第一步是建立数据库。正如您可能猜到的,可使用命令 来实现。而后切换到新建立的数据库。数据库

 

这种语义对你来讲是否熟悉?是的, 为 提供了很是类似的查询语言。它被称为 ,容许您定义 语句, 或 子句等等。可是,在执行此类查询以前,咱们应该将数据存储在数据库中,对吗?如今,让咱们继续下一步,以生成一些测试指标。安全

将Spring Boot应用程序与InfluxDB集成springboot

若是您将工件 包含在项目的依赖项中,则会自动启用对InfluxDB的导出。固然,咱们还须要包括网络

 

您惟一要作的就是覆盖 默认地址,由于咱们在 上运行 容器。默认状况下, 尝试链接名为 的数据库。可是,我已经建立了数据库 ,因此我也应该覆盖这个默认值。在 的第2版中,与 端点相关的全部配置属性都已移至 部分。

 

在使用类路径中包含的执行器启动 应用程序后,您可能会感到惊讶,它默认只显示两个HTTP端点/执行器/信息和/执行器/运行情况。这就是为何在最新版本的 中,出于安全目的,默认状况下禁用除 和 以外的全部执行器。要启用全部执行器链接点,必须将属性 设置为'*'。在最新版本的 中, 指标的监控获得了显着改善。咱们能够经过将属性 设置为 来启用收集全部 指标。或者,当它设置为 时,您能够经过使用 对其进行注释来启用特定REST控制器的度量标准。您还能够在控制器内注释单个方法,以仅为特定端点生成度量。应用程序启动后,您能够经过调用端点 来查看生成的指标的完整列表。默认状况下, 控制器的度量标准以名称 生成。能够经过设置 属性来自定义此名称。若是您运行个人 存储库中可用的示例应用程序,则默认状况下可使用uder端口 .如今,您能够经过调用端点 来查看为单个度量标准生成的统计信息列表,以下图所示

 

 

构建 应用程序用于生成度量的示例 应用程序由单个控制器组成,该控制器实现用于操做 实体,存储库 和实体类的基本 操做。应用程序使用提供 实现的 存储库链接到 数据库。这是控制器类。

 

在运行应用程序以前,咱们设置了 数据库。实现它的最方便的方法是经过 镜像。这是使用数据库 运行容器的命令,定义用户和密码,并在端口 上公开 。

 

而后咱们须要在应用程序端设置一些数据库配置属性。全部必需的表都将在应用程序启动时建立,这要归功于设置属性 进行更新。

 

生成指标

在启动应用程序和所需的 容器以后,惟一须要作的就是生成一些测试统计信息。我建立了 测试类,它生成一些测试数据并在循环中调用应用程序公开的端点。这是该测试方法的片断。

 

如今,让咱们回到第1步。您可能还记得,我已经向您展现了如何在 容器中运行涌入客户端。通过几分钟的工做后,测试单元应屡次调用暴露的端点。咱们能够查看 上存储的度量标准 的值。如下查询返回最近3分钟内收集的测量值列表。

如您所见, 生成的全部指标都标有如下信息: , , 和 。因为这些标签,咱们能够轻松地为每一个信号端点分组指标,包括失败和成功百分比。咱们来看看如何在 中配置和查看它。

使用 进行度量标准可视化

一旦咱们将成功的指标导出到 ,就可使用 将它们可视化了。首先,让咱们用 运行 容器。

为用户提供了用于建立大量涌入查询的界面。咱们定义了一个图形,可视化每一个呼叫端点的请求处理时间和应用程序接收的请求总数。若是咱们按方法类型和 过滤存储在表 中的统计信息,咱们将收集每一个端点生成的全部度量标准。

应为其余端点建立相似的定义。咱们将在一张图上说明它们。

这是最终的结果。

 

 

这是可视化发送到应用程序的请求总数的图表。

 

 

运行

在本地运行 最合适的方法显然是经过 容器。 API在端口 下公开。咱们还应该传递初始配置文件和 网络的名称。为何?您将在本步骤说明的下一部分找到全部的答案。

 

与 相比, 从应用程序中提取指标。所以,咱们须要启用公开 指标的执行器端点,默认状况下禁用该指标。要启用它,请将property 设置为 ,以下面的配置片断所示。

 

而后咱们应该在 配置文件中设置应用程序公开的执行器端点的地址。 部分负责指定一组目标和参数,描述如何与它们链接。默认状况下, 会尝试每分钟从定义的目标端点收集数据。

 

与 的集成相似,咱们须要将如下工件包含在项目的依赖项中。

 

在个人例子中, 在 上运行,而且在IP 下可用。若是我想要做为 容器启动的 可以链接个人应用程序,我也应该将它做为 容器启动。连接两个独立容器的最方便方法是经过 网络。若是两个容器都分配到同一网络,则它们可使用容器的名称做为目标地址相互链接。 位于示例应用程序源代码的根目录中。下面显示的第二个命令( )不是必需的,由于个人 存储库中提供了所需的图像

 

将 Prometheus整合进Grafana

在地址 下公开 控制台,您能够在其中指定带有指标的查询和显示图形。可是,咱们能够将它与 集成,以利用此工具提供的更好的可视化。首先,您应该建立 数据源。

 

 

而后咱们应该定义从 收集指标的查询。 公开了与 流量相关的三种不一样指标: , 和 。例如,咱们能够计算 的时间序列的每秒平均增加率,它返回使用 函数处理请求所花费的总秒数。可使用方法和 使用 内的表达式过滤这些值。下图说明了每一个端点的rate()函数配置。

 

 

这是图表。

 

 

总结

版本 和 之间的度量标准生成的改进很是重要。将数据导出到诸如 或 之类的流行监控系统如今比之前容易得多,而且不须要任何额外的开发。因为标签指示了 请求的uri,类型和状态,所以与HTTP流量相关的指标更加详细,而且能够轻松地与特定端点关联。我认为 中与 的早期版本相关的修改多是将应用程序迁移到最新版本的主要动机之一。

做者:piotr

关注公众号


 

 

运行InfluxDB

在上一篇文章中,我没有写太多关于这个数据库及其配置的内容。因此,如今我说一些关于它的话。第一步是个人示例的典型步骤 - 咱们将使用 InfluxDB运行 Docker容器。这是在本地计算机上运行 InfluxDB并在 8086端口上公开 HTTP API的最简单命令。 $ docker run-d--name influx-p8086:8086influxdb

一旦咱们启动了该容器,您可能但愿在那里登陆并执行一些命令。没有比这更简单的了,只需运行如下命令便可。登陆后,您应该看到目标Docker容器上运行的InfluxDB版本。

  1. $ docker exec -it influx influx

  2. Connected to http://localhost:8086 version 1.5.2

  3. InfluxDB shell version: 1.5.2

第一步是建立数据库。正如您可能猜到的,可使用命令 create database来实现。而后切换到新建立的数据库。

  1. $ create database springboot

  2. $ use springboot

这种语义对你来讲是否熟悉?是的, InfluxDB为 SQL提供了很是类似的查询语言。它被称为 InluxQL,容许您定义 SELECT语句, GROUP BY或 INTO子句等等。可是,在执行此类查询以前,咱们应该将数据存储在数据库中,对吗?如今,让咱们继续下一步,以生成一些测试指标。

将Spring Boot应用程序与InfluxDB集成

若是您将工件 micrometer-registry-Influx包含在项目的依赖项中,则会自动启用对InfluxDB的导出。固然,咱们还须要包括 spring-boot-starter-actuator

  1. <dependency>

  2.    <groupId>org.springframework.boot</groupId>

  3.    <artifactId>spring-boot-starter-actuator</artifactId>

  4. </dependency>

  5. <dependency>

  6.    <groupId>io.micrometer</groupId>

  7.    <artifactId>micrometer-registry-influx</artifactId>

  8. </dependency>

您惟一要作的就是覆盖 InfluxDB的默认地址,由于咱们在 VM上运行 InfluxDBDocker容器。默认状况下, SpringBootData尝试链接名为 mydb的数据库。可是,我已经建立了数据库 springboot,因此我也应该覆盖这个默认值。在 SpringBoot的第2版中,与 SpringBootActuator端点相关的全部配置属性都已移至 management.*部分。

  1. management:

  2.  metrics:

  3.    export:

  4.      influx:

  5.        db: springboot

  6.        uri: http://192.168.99.100:8086

在使用类路径中包含的执行器启动 SpringBoot应用程序后,您可能会感到惊讶,它默认只显示两个HTTP端点/执行器/信息和/执行器/运行情况。这就是为何在最新版本的 SpringBoot中,出于安全目的,默认状况下禁用除 /health和 /info以外的全部执行器。要启用全部执行器链接点,必须将属性 management.endpoints.web.exposure.include设置为'*'。 在最新版本的 SpringBoot中, HTTP指标的监控获得了显着改善。咱们能够经过将属性 management.metrics.web.server.auto-time-requests设置为 true来启用收集全部 SpringMVC指标。或者,当它设置为 false时,您能够经过使用 @Timed对其进行注释来启用特定REST控制器的度量标准。您还能够在控制器内注释单个方法,以仅为特定端点生成度量。 应用程序启动后,您能够经过调用端点 GET/actuator/metrics来查看生成的指标的完整列表。默认状况下, SpringMVC控制器的度量标准以名称 http.server.requests生成。能够经过设置 management.metrics.web.server.requests-metric-name属性来自定义此名称。若是您运行个人 GitHub存储库中可用的示例应用程序,则默认状况下可使用uder端口 2222.如今,您能够经过调用端点 GET/actuator/metrics/{requiredMetricName}来查看为单个度量标准生成的统计信息列表,以下图所示

 

 

构建 SpringBoot应用程序 用于生成度量的示例 SpringBoot应用程序由单个控制器组成,该控制器实现用于操做 Person实体,存储库 bean和实体类的基本 CRUD操做。应用程序使用提供 CRUD实现的 SpringDataJPA存储库链接到 MySQL数据库。这是控制器类。

  1. @RestController

  2. @Timed

  3. public class PersonController {

  4.    protected Logger logger = Logger.getLogger(PersonController.class.getName());

  5.    @Autowired

  6.    PersonRepository repository;

  7.    @GetMapping("/persons/pesel/{pesel}")

  8.    public List findByPesel(@PathVariable("pesel") String pesel) {

  9.        logger.info(String.format("Person.findByPesel(%s)", pesel));

  10.        return repository.findByPesel(pesel);

  11.    }

  12.    @GetMapping("/persons/{id}")

  13.    public Person findById(@PathVariable("id") Integer id) {

  14.        logger.info(String.format("Person.findById(%d)", id));

  15.        return repository.findById(id).get();

  16.    }

  17.    @GetMapping("/persons")

  18.    public List findAll() {

  19.        logger.info(String.format("Person.findAll()"));

  20.        return (List) repository.findAll();

  21.    }

  22.    @PostMapping("/persons")

  23.    public Person add(@RequestBody Person person) {

  24.        logger.info(String.format("Person.add(%s)", person));

  25.        return repository.save(person);

  26.    }

  27.    @PutMapping("/persons")

  28.    public Person update(@RequestBody Person person) {

  29.        logger.info(String.format("Person.update(%s)", person));

  30.        return repository.save(person);

  31.    }

  32.    @DeleteMapping("/persons/{id}")

  33.    public void remove(@PathVariable("id") Integer id) {

  34.        logger.info(String.format("Person.remove(%d)", id));

  35.        repository.deleteById(id);

  36.    }

  37. }

在运行应用程序以前,咱们设置了 MySQL数据库。实现它的最方便的方法是经过 MySQLDocker镜像。这是使用数据库 grafana运行容器的命令,定义用户和密码,并在端口 33306上公开 MySQL5

  1. docker run -d --name mysql -e MYSQL_DATABASE=grafana -e MYSQL_USER=grafana -e MYSQL_PASSWORD=grafana -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -p 33306:3306 mysql:5

而后咱们须要在应用程序端设置一些数据库配置属性。全部必需的表都将在应用程序启动时建立,这要归功于设置属性 spring.jpa.properties.hibernate.hbm2ddl.auto进行更新。

  1. spring:

  2.  datasource:

  3.    url: jdbc:mysql://192.168.99.100:33306/grafana?useSSL=false

  4.    username: grafana

  5.    password: grafana

  6.    driverClassName: com.mysql.jdbc.Driver

  7.  jpa:

  8.    properties:

  9.      hibernate:

  10.        dialect: org.hibernate.dialect.MySQL5Dialect

  11.        hbm2ddl.auto: update

生成指标

在启动应用程序和所需的 Docker容器以后,惟一须要作的就是生成一些测试统计信息。我建立了 JUnit测试类,它生成一些测试数据并在循环中调用应用程序公开的端点。这是该测试方法的片断。

  1. int ix = new Random().nextInt(100000);

  2. Person p = new Person();

  3. p.setFirstName("Jan" + ix);

  4. p.setLastName("Testowy" + ix);

  5. p.setPesel(new DecimalFormat("0000000").format(ix) + new DecimalFormat("000").format(ix%100));

  6. p.setAge(ix%100);

  7. p = template.postForObject("http://localhost:2222/persons", p, Person.class);

  8. LOGGER.info("New person: {}", p);

  9. p = template.getForObject("http://localhost:2222/persons/{id}", Person.class, p.getId());

  10. p.setAge(ix%100);

  11. template.put("http://localhost:2222/persons", p);

相关文章
相关标签/搜索