Bootstrap

项目优化之系统监控Prometheus-Grafana

项目事前思考

需要了解清楚:需要从哪些角度去分析实现?
	使用了缓存,就需要把缓存命中率数据进行收集;
	使用了数据库连接池,就把连接池的参数给暴露出来;

Prometheus 普罗米修斯

概述

定义:
	Prometheus作为一个开源的监控和告警工具,具有强大的数据采集、存储和查询能力;
介绍:
	它通过采集和存储指标(metrics),提供了强大的数据查询语言,可以帮助我们分析和理解应用程序的行为。
	Prometheus 的核心组件是 Prometheus Server,它负责采集监控指标并提供查询接口。
	Prometheus 监控服务基于 Spring Actuator 机制采集 JVM 等数据,结合配套提供的 Grafana Dashboard 可以方便地监控 Spring Boot 应用的状态。
特点:
	易于管理:Prometheus 核心部分只有一个单独的二进制文件;Prometheus 基于 Pu 模型的架构方式;
	监控服务的内部运行状态:基于 Prometheus 丰富的 Client 库,用户可以轻松的在应用程序中添加对 Prometheus 的支持;
	强大的数据模型:所有采集的监控数据均以指标(metric)的形式保存在内置的时间序列数据库当中(TSDB)。
	强大的查询语言PromQL:通过 PromQL 可以实现对监控数据的查询、聚合。同时 PromQL 也被应用于数据可视化(Grafana)以及告警当中;
	高效:可以处理数以百万的监控指标;
	可扩展性:当单例Prometheus Server 处理的任务量过大时,通过使用功能分区(sharding)+联邦集群(federation)可以对其进行扩展;
	易于集成:使用 Prometheus 可以快速搭建监控服务,并且可以非常方便地在应用程序中进行集成;
	可视化:Prometheus Server 中自带的 Prometheus Ul,可以方便地直接对数据进行査询;
	开放性:支持在外部创建单独的服务来适配不同的监控系统;

注意:
	grafana、Prometheus 会独立部署在一台机器上,node_export 则被部署在被监控的服务器上,收集被监控的服务器资源数据,给 Prometheus,然后再通过 grafana 展示出来。

架构

它是一个维度存储模型,

在这里插入图片描述

安装及使用

参考:
	普通安装 https://blog.csdn.net/dazhong2012/article/details/139288005
	docker安装 https://www.cnblogs.com/sheepboy/p/17242916.html

安装步骤:

🍎 docker命令行,下载镜像包prometheus,并完成安装;
方法1:
直接通过docker pull 下载,由于网络超时问题,会导致下载异常;故此采用博客中提供的网盘链接下载 ;
解压:tar -xvf images_prmetheus.tar.gz ; 
采用docker实现xxx.tar.gz导入docker中:一种for命令 一种脚本方式
	for循环方式不能实现执行:for %%i in (*) do @docker load -i "%%i"
	脚本方式执行:执行脚本方法也不可行;
	
方法2:
更换镜像;执行后续操作;
// 拉取镜像image
	docker pull prom/prometheus 
// 创建containers
	docker run --name prometheus -d -p 9090:9090 prom/prometheus 
	// 需要自定义配置部署的,执行该条命令,-v后的内容是将主机自定义的prometheus.yml文件挂在到容器中;
	docker run -d --name prometheus -p 9090:9090 -v D:\soft\Prometheus\prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus 
// 浏览器访问查看prometheus启动情况
浏览器访问:http://localhost:9090    结果可以看到下图;
// 将prometheus.yml文件拷贝到宿主主机上,即从contains中拷贝到本地
docker cp prometheus:/etc/prometheus/prometheus.yml  D:\soft\Prometheus\prometheus.yml
拷贝后结果为空?可能本来就是空的。
// 配置prometheus.yml文件

方法1-过程图1
在这里插入图片描述
方法1-文件解压代码1-不可用;

@echo off
setlocal enabledelayedexpansion
cd /d D:\soft\Prometheus\gz\images_prometheus
for %%i in (*.tar) do (
    echo Loading %%i...
    docker load -i "%%i"
)
endlocal

🍎 prometheus.yml文件

如下内容:
scrape_configs:
  - job_name: 'spring-boot-application' //定义任务抓取的名字 应该是springboot-application-name
    metrics_path: 'prometheus-demo/actuator/prometheus' // 指定Prometheus从目标服务器的哪个路基你个去获取度量指标;
    scrape_interval: 15s // 设置抓取目标间隔的时间
    static_configs: 
      - targets: ['192.168.10.108:8091'] // 抓取数据的服务地址ip和port

🍇注意:
	targets中的ip如果是本地,不能使用localhost实现,而得采用ipconfig查看本地得到的ip地址;	

🍎 prometheus启动成功,通过访问localhost:9090即可显示如下页面;
在这里插入图片描述
🍎 查询项目中配置的度量
在这里插入图片描述

simpleclient实现监控

实现步骤:

1. 项目pom.xml文件中添加依赖项;
dependency>
	<groupId>io.prometheus</groupId>
	<artifactId>simpleclient</artifactId>
	<version>0.16.0</version>
</dependency>
<dependency>
	<groupId>io.prometheus</groupId>
	<artifactId>simpleclient_httpserver</artifactId>
	<version>0.16.0</version>
</dependency>

2. 初始化HTTP服务器来暴露metrics端点,使用simpleclient_httpserver来启动默认的HTTP服务器;
通过return new HTTPServer(prometheusPort); 语句实现;
// 其中prometheusPort是端口号,用来暴露metrics的;

3. 记录数据,通过simpleclient提供的API记录指标数据;

4. 配置prometheus文件,抓取metrics;
scrape_configs:
  - job_name: '所监控服务的名字' // 即spring.application.name
    static_configs:
      - targets: ['localhost:9190'] // 所监控服务的ip以及metrics暴露的端口号;

6. 测试,启动应用和prometheus,访问应用的metrics端点,http请求为:
http://localhost:9190/metrics  // 其中ip和端口号于prometheus保持一致;
// 并且端口号与步骤二中的prometheusPort保持一致;

🍓具体实例在实战2

PromQL

学习文档:https://prometheus.wang/promql/



io.prometheus.client库

统计接口调用量 每分钟或每秒钟;
请求的延迟时间
查看redis缓存容量;
查看本地缓存容量;
监控服务器内存使用情况;

1. 计数器定义
Counter REQUEST_TOTAL = Counter.build() // 创建计数器对象
            .name("") // 定义指标名称
            .help("") // 添加指标解释信息
            .labelNames(PATH, APP_ID) // 定义区分指标的维度
            .register(); // 注册计数器到Prometheus的注册中心
// 应用场景:统计某个接口调用量;统计某个应用调用量;

2. Summary,收集数据分布的信息
Summary HTTP_REQUEST_DURATION = Summary.build() // 创建Summary构造器对象
            .name("") // 定义指标名称
            .help("") // 添加指标解释信息
            .labelNames(NAME, "subName", APP_ID) // 定义区分指标的维度
            .quantile(0.5, 0.05) // 定义百分位点,以及误差
            .quantile(0.9, 0.01) // 计算第90百分位,误差最多1%;
            .quantile(0.99, 0.001)
            .register(); // 注册到Prometheus的注册中心
// 特点:不划分区间,记录数值的总和及样本数;手动定义百分位;存储信息较少;开销小
// 应用场景:统计延迟时间;

3. Gauge,随时改变的数值的度量
Gauge CHANGE_GAUGE = Gauge.build()
            .name("") // 定义指标名称
            .help("") // 添加指标解释信息
            .labelNames(NAME) // 定义区分指标的维度
            .register(); // 注册到Prometheus的注册中心
// 应用场景:cache中的key所占内存;

4. Histogram 收集数据分布的信息
Histogram LATENCY_HISTOGRAM = Histogram.build()
            .name("") // 定义指标名称
            .help("") // 添加指标解释信息
            .labelNames(NAME, "subName", APP_ID) // 定义区分指标的维度
            .buckets(10, 50, 100, 200, 300, 500, 800, 1000, 1500, 3000, 10000) // 定义多个桶,表示延迟时间的区间范围 单位ms
            .register(); // 注册到Prometheus的注册中心
// 特点:划分区间;提供百分位数;存储更多信息;开销大;

展示:

所遇问题

问题1:simpleclient 、simpleclient_httpserver、micrometer-registry-promethheus之间的区别?

前者,simpleclient 和 simpleclient_httpserver 是Prometheus客户端库的一部分,它们允许你在Java应用程序中直接记录度量数据,并提供一个简单的HTTP服务器来暴露这些度量数据给Prometheus抓取。
后者,micrometer-registry-prometheus: 这个依赖项允许你使用Micrometer来记录度量,并且将这些度量发布到Prometheus。

前者,需要手动管理度量的创建和暴露;更适合对监控有具体需求的情况;需要更多手动配置才可以提供更细的颗粒度;
后者,Micrometer提供了一个抽象层,使得度量的注册和暴露更加容易,尤其是对于那些想要快速集成监控而不想深入细节的应用程序。

Grafana可视化

概述

定义:
	grafana,一个开源的可视化平台;
	时序数据展示工具;
特征:
	常用数据源有:MySQL、prometheus、elasticsearch等;
	通过插件来显示数据;

安装及登录

docker 安装 :https://blog.csdn.net/dazhong2012/article/details/139288005

🍎 安装及运行:

安装镜像:
	docker pull grafana/grafana
创建并运行容器:
	docker  run -d --name=grafana  -p 3000:3000  grafana/grafana
访问grafana:
	http://localhost:3000
	账号-密码:xxxadmin-xxxadmin 

使用及问题

🍎 项目配置:
🍇 添加数据源
在这里插入图片描述
🍇 验证配置数据集是否正常运行
在这里插入图片描述

🍎 问题1:与prometheus配置异常

描述:
	Post "http://localhost:9090/api/v1query": dialtcp 127.0.0.1:9090: connect: connection refused - There was an error returned querying the Prometheus Apl.
	
分析:
	访问的问题,不能使用localhost这个单词;
	windows系统通过ipconfig得到本机ip地址,将localhost替换为查询到ip;
	127.0.0.1 这个地址是不可行的;具体本机ip得出方式见下图;

在这里插入图片描述

展示度量参数

🍎 手动创建仪表盘Dashboard

具体操作:
	dashboard --> create dashboard --> add viusalization --> select data source
	
1. 创建panel还是row
	选择pannel;
	视频中,涉及到创建panel还是row,row可以放多个panel;
	当前grafana中只涉及到panel;
2. 查询度量参数

在这里插入图片描述
在这里插入图片描述
🍎 导入现成模板

网站:https://grafana.com/grafana/dashboards/
选择:
	基于下载数量、reviews检查、
下载:
	download json
	案例中涉及到的是flink模板;

数据库读写分离

实战

实战1-Prometheus+Grafana+springboot

🍎 一、储备与思考

Prometheus 监控项目执行的情况,即执行环境的情况(指标采集);
Grafana 将监控情况进行展现;
睿象云 实现异常报警;

思考1Premetheus是否可以检测到项目运行是否正常,是否可以评估当前系统前后阶段是否数量一致?

🍎 二、整体步骤

1. 在springboot项目中添加Springboot ActuatorMicrometer prometheus Registry依赖,以及Actuator配置;
2. 下载镜像包prometheus并完成安装,在docker中; 
	参考 https://blog.csdn.net/qq_44246980/article/details/119981183 该方案失败。
	参考 https://blog.csdn.net/dazhong2012/article/details/139288005 该方案失败,目前该方案进展。
	参考 https://blog.csdn.net/2403_87851141/article/details/142733680 替换镜像,成功。

🍇1、springboot项目中涉及到prometheus的配置;

1 依赖:
	Actuator 提供了一系列内置端点,用于显示运行应用的性能信息,如健康状况、指标等。
	Micrometer Prometheus registry 会将这些指标格式化为 Prometheus 可读格式。
	具体依赖:
		
2 配置 Actuator:
	management: // 定义管理相关的配置
	  endpoints: // 指定关于应用端点的配置
	    web: // web端点的配置
	      exposure: //哪些端点通过web暴露出来
	        include: '*' // 所有管理端点
	  metrics: // 配置与度量指标相关的选项
	    export: // 指定度量指标导出的相关配置
	      prometheus: // 特定于prometheus的配置
	        enabled: true // 启动prometheus格式的度量指标导出
    已知项目:只采用endpoints这个配置;且只启动了health
    include参数介绍:health--应用程序的健康信息;info--应用程序的基本信息;metrics--应用程序的各种度量指标,如CPU使用率等;prometheus--暴露prometheus格式的度量指标;

🍇 2 docker命令行启动,下载镜像包prometheus,并完成安装;

方法1:
直接通过docker pull 下载,由于网络超时问题,会导致下载异常;故此采用博客中提供的网盘链接下载 ;
解压:tar -xvf images_prmetheus.tar.gz ; 
采用docker实现xxx.tar.gz导入docker中:一种for命令 一种脚本方式
	for循环方式不能实现执行:for %%i in (*) do @docker load -i "%%i"
	脚本方式执行:执行脚本方法也不可行;
方法2:
更换镜像;执行后续操作;
// 拉取镜像image
	docker pull prom/prometheus 
// 创建containers
	docker run --name prometheus -d -p 9090:9090 prom/prometheus 
	// 需要自定义配置部署的,执行该条命令,-v后的内容是将主机自定义的prometheus.yml文件挂在到容器中;
	docker run -d --name prometheus -p 9090:9090 -v D:\soft\Prometheus\prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus 
// 浏览器访问查看prometheus启动情况
浏览器访问:http://localhost:9090    结果可以看到下图;
// 将prometheus.yml文件拷贝到宿主主机上,即从contains中拷贝到本地
docker cp prometheus:/etc/prometheus/prometheus.yml  D:\soft\Prometheus\prometheus.yml
拷贝后结果为空?可能本来就是空的。
// 配置prometheus.yml文件

在这里插入图片描述

@echo off
setlocal enabledelayedexpansion
cd /d D:\soft\Prometheus\gz\images_prometheus
for %%i in (*.tar) do (
    echo Loading %%i...
    docker load -i "%%i"
)
endlocal

prometheus启动成功,通过访问localhost:9090即可显示如下页面;
在这里插入图片描述

prometheus.yml文件
如下内容:
scrape_configs:
  - job_name: 'spring-boot-application' //定义任务抓取的名字 应该是springboot-application-name
    metrics_path: 'prometheus-demo/actuator/prometheus' // 指定Prometheus从目标服务器的哪个路基你个去获取度量指标;
    scrape_interval: 15s // 设置抓取目标间隔的时间
    static_configs: 
      - targets: ['192.168.10.108:8091'] // 抓取数据的服务地址ip和port

实战2-simpleclient+prometheus+grafana

整体流程:
1. 项目配置文件准备
pom.xml依赖导入;
HTTPserver服务配置类编写;
度量指标自定义编写;

2. prometheus服务配置文件编写
该文件位于本地prometheus的安装目录;Prometheus.yml文件

3. 运行项目测试prometheus
通过http://localhost:port 实现

结合 Grafana服务

🍎一、项目配置文件准备

4. pom依赖导入
<dependency>
    <groupId>io.prometheus</groupId>
    <artifactId>simpleclient</artifactId>
    <version>0.16.0</version>
</dependency>
<dependency>
    <groupId>io.prometheus</groupId>
    <artifactId>simpleclient_httpserver</artifactId>
    <version>0.16.0</version>
</dependency>

5. prometheusConfig文件编写
import io.prometheus.client.exporter.HTTPServer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import java.io.IOException;

@Configuration
@ConditionalOnProperty(
        value = {"prometheus.enabled"},
        havingValue = "true",
        matchIfMissing = true
)
public class PrometheusConfig {

    @Value("${prometheus.port:9090}")
    private int prometheusPort;
    
    @Bean(name = "prometheusServer", destroyMethod = "stop")
    @Scope(value = "singleton")
    public HTTPServer prometheusServer() throws IOException {
        return new HTTPServer(prometheusPort);
    }
}

3. 度量指标编写
import io.prometheus.client.Counter; // 记录某个初始点以来累计数量的度量类型;
import io.prometheus.client.Gauge;
// Gauge 用于记录瞬时值,可以任意上下浮动。它能够反映当前系统状态的一个快照,如内存使用情况、活跃连接数等。
import io.prometheus.client.Histogram;
// Histogram 用于收集数值分布,通常用来记录操作的耗时。它可以提供关于数据分布的统计信息,如平均值、中位数等。
import io.prometheus.client.Summary;
// Summary 类似于Histogram,但它的实现更高效,因为它不需要存储所有的桶(buckets)。Summary 通常用于记录数值的分布,但不提供完整的分布信息,而是只提供简单的汇总统计信息。

public interface PrometheusConsts {
    String APP_ID = "appId";
    String PATH = "path";
    String NAME = "name";

    /**
     * 所有的请求的统计
     */
    Counter REQUEST_TOTAL = Counter.build()
            .name("")
            .help("")
            .labelNames(PATH, APP_ID)
            .register();

    Summary HTTP_REQUEST_DURATION = Summary.build()
            .name("")
            .help("")
            .labelNames(NAME, "subName", APP_ID)
            .quantile(0.5, 0.05)
            .quantile(0.9, 0.01)
            .quantile(0.99, 0.001)
            .register();

    /**
     * 记录cache中的keys和所占内存
     */
    Gauge CHANGE_GAUGE = Gauge.build()
            .name("")
            .help("")
            .labelNames(NAME)
            .register();


    /**
     * method name以及是哪个APP_ID的
     */
    Histogram LATENCY_HISTOGRAM = Histogram.build()
            .name("")
            .help("")
            .labelNames(NAME, "subName", APP_ID)
            .buckets(10, 50, 100, 200, 300, 500, 800, 1000, 1500, 3000, 10000)
            .register();
}

🍎二 、prometheus服务配置文件编写

scrape_configs:
  - job_name: '所监控服务的名字' // 即spring.application.name
    static_configs:
      - targets: ['localhost:9190'] // 所监控服务的ip以及metrics暴露的端口号;

🍎 三、prometheus结果查看

http://localhost:9090

# HELP lz_server_requests_total Total number of requests.
# TYPE lz_server_requests_total counter
lz_server_requests_total{path="xxx",appId="xxx",} 1.0
# HELP http_request_duration_millis HTTP request latency in milliseconds.
# TYPE http_request_duration_millis summary
.....
;