使用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);

相關文章
相關標籤/搜索