《企业实战分享 · Prometheus 运用》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗
🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍

CSDN.gif


Prometheus

技术简介

Prometheus 是一个开源的监控和报警工具,最初由 SoundCloud 开发。它主要用于收集和存储时间序列数据,特别适合于微服务架构和云原生应用。Prometheus 的设计理念是简单、灵活和高效,广泛应用于现代 DevOps 和监控解决方案中。

主要特性:
多维数据模型:Prometheus 使用标签(labels)来标识时间序列数据,使得用户可以灵活地对数据进行分组和聚合。
强大的查询语言:PromQL(Prometheus Query Language)是 Prometheus 的查询语言,允许用户对数据进行复杂的查询和计算。
数据收集:Prometheus 通过 HTTP 拉取(pull)方式定期从被监控的服务中收集指标数据,也支持推送(push)方式,适用于短暂存在的服务。
高效的存储:Prometheus 使用时间序列数据库,能够高效地存储和压缩数据,支持高频率的数据采集。
报警功能:Prometheus 提供了强大的报警功能,可以根据用户定义的规则生成报警,并支持多种通知渠道(如邮件、Slack、PagerDuty 等)。
可视化:虽然 Prometheus 本身不提供可视化界面,但它可以与 Grafana 等工具集成,提供丰富的图表和仪表板。
服务发现:Prometheus 支持多种服务发现机制,可以自动发现和监控动态环境中的服务。

应用场景:
微服务架构的监控
云原生应用的性能监控
系统资源监控(CPU、内存、磁盘等)
应用程序性能监控(APM)


采集 Druid 指标

前提:默认已经准备好一个完整的SpringBoot项目,并且已经整合了Druid

Step1、添加 Pom 依赖

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

Step2、在 application.yml 中配置 Actuator 和 Prometheus

management:
  endpoints:
    web:
      exposure:
        # 仅暴露 prometheus、health 和 info 端点。
        include: prometheus, health, info
  metrics:
    export:
      prometheus:
        # 启用 Prometheus 指标导出。
        enabled: true
  endpoint:
    prometheus:
      # 启用 /prometheus 端点。
      enabled: true

Step3、注册 Druid 数据源的指标到 Micrometer

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(DruidDataSource.class)
static class DruidDataSourcePoolMetadataProviderConfiguration implements SmartInitializingSingleton {
    private DruidDataSource wrappedDataSource;
    
    @Bean
    public DataSourcePoolMetadataProvider druidPoolDataSourceMetadataProvider() {
        return (dataSource) -> {
            DruidDataSource ds = DataSourceUnwrapper.unwrap(dataSource, DruidDataSource.class);
            if (ds != null) {
                this.wrappedDataSource = ds;
                return new DruidDataSourcePoolMetadata(ds);
            }
            return null;
        };
    }
    
    @Override
    public void afterSingletonsInstantiated() {
        if (this.wrappedDataSource == null) {
            return;
        }
        Metrics.gauge(MetricsConstant.DataSource.POOLING_COUNT, this.wrappedDataSource, DruidDataSource::getPoolingCount);
        Metrics.gauge(MetricsConstant.DataSource.CONNECT_OPEN_COUNT, this.wrappedDataSource, DruidDataSource::getConnectCount);
        Metrics.gauge(MetricsConstant.DataSource.CONNECT_CLOSE_COUNT, this.wrappedDataSource, DruidDataSource::getCloseCount);
        Metrics.gauge(MetricsConstant.DataSource.CONNECT_ERROR_COUNT, this.wrappedDataSource, DruidDataSource::getConnectErrorCount);
        Metrics.gauge(MetricsConstant.DataSource.EXECUTE_COUNT, this.wrappedDataSource, DruidDataSource::getExecuteCount);
        Metrics.gauge(MetricsConstant.DataSource.ROLLBACK_COUNT, this.wrappedDataSource, DruidDataSource::getRollbackCount);
        Metrics.gauge(MetricsConstant.DataSource.PHYSICAL_CONNECT_COUNT, this.wrappedDataSource, DruidDataSource::getCreateCount);
        Metrics.gauge(MetricsConstant.DataSource.PHYSICAL_CLOSE_COUNT, this.wrappedDataSource, DruidDataSource::getDestroyCount);
        Metrics.gauge(MetricsConstant.DataSource.PHYSICAL_CONNECT_ERROR_COUNT, this.wrappedDataSource, DruidDataSource::getCreateErrorCount);
        Metrics.gauge(MetricsConstant.DataSource.NOT_EMPTY_WAIT_COUNT, this.wrappedDataSource, DruidDataSource::getNotEmptyWaitCount);
        Metrics.gauge(MetricsConstant.DataSource.NOT_EMPTY_WAIT_MILLIS, this.wrappedDataSource, DruidDataSource::getNotEmptyWaitMillis);
    }
}

Step4、配置 Prometheus 抓取 Spring Boot 应用的指标
进入Prometheus所在服务器,修改配置文件prometheus.yml
如下所示,是配置具体某个服务,如果是SpringCloud,有接入网关,也可以通过网关配置。

scrape_configs:
  - job_name: 'spring-boot-app'
    static_configs:
      - targets: ['localhost:8080']

Step5、启动 Spring Boot 应用并检查指标
访问地址:http://127.0.0.1:28888//actuator/prometheus
应该可以看到如下图所示的相关指标信息,包括 Druid 数据源的指标。
image.png

Step6、打开 Prometheus 界面验证
启动 Prometheus,访问地址:http://localhost:9090
在 Prometheus 的界面中可以看到从 Spring Boot 应用中抓取到的指标数据,操作效果如下图:
image.png


采集 OkHttp3 指标

需求背景
框架采用OkHttp3作为远程调用工具,现在也需要采集相关指标到Prometheus
这里基本实现思路,类似前面的Druid整合方案。
1、瞬时类型的指标,可以在初始化的时候利用Metrics.gauge注册;
2、请求耗时这样的指标,可以借助 OkHttp3 的拦截器,计算耗时,再利用Metrics.timer注册;

Metrics.gauge 和 Metrics.timer 区别
Metrics.gauge 收集的是瞬时数据(instantaneous data),也就是某一时刻的数值。这些数据通常反映了当前状态或当前值,例如内存使用量、线程数、队列长度等。
Metrics.timer 收集的是区间数据(interval data),也就是一段时间内的多个数据点。这些数据点可以用于计算统计信息,比如平均值、最小值、最大值等。
通过这两种不同的度量方式,可以全面地监控和分析应用程序的性能和状态。

具体代码案例

public class HttpClientMetricsInterceptor implements Interceptor {

    public HttpClientMetricsInterceptor(Dispatcher dispatcher) {
        Assert.notNull(dispatcher, "OkHttp dispatcher could not be null");
        Metrics.gauge(HttpClient.MAX_REQ_PER_HOST_SIZE, dispatcher.getMaxRequestsPerHost());
        Metrics.gauge(HttpClient.MAX_REQ_SIZE, dispatcher.getMaxRequests());
        Metrics.gauge(HttpClient.REQ_RUNNING_COUNT, dispatcher, Dispatcher::runningCallsCount);
        Metrics.gauge(HttpClient.REQ_QUEUE_TASK_COUNT, dispatcher, Dispatcher::queuedCallsCount);
        ExecutorService executorService = dispatcher.executorService();
        if (executorService instanceof ThreadPoolExecutor) {
            ThreadPoolExecutor executor = (ThreadPoolExecutor) executorService;
            Metrics.gauge(HttpClient.MAX_POOL_SIZE, executor, ThreadPoolExecutor::getMaximumPoolSize);
            Metrics.gauge(HttpClient.CORE_POOL_SIZE, executor, ThreadPoolExecutor::getCorePoolSize);
            Metrics.gauge(HttpClient.ACTIVE_POOL_COUNT, executor, ThreadPoolExecutor::getActiveCount);
            Metrics.gauge(HttpClient.LARGEST_POOL_SIZE, executor, ThreadPoolExecutor::getLargestPoolSize);
        }
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Timer.Sample sample = Timer.start(Metrics.globalRegistry);
        Request request = chain.request();
        Response response = null;
        try {
            response = chain.proceed(request);
        } finally {
            String threadName = Thread.currentThread().getName();
            boolean async = StrUtil.startWith(threadName, "okhttp", true);
            Timer timer = Metrics.timer(HttpClient.RESP_TIME,
                    "method", request.method(),
                    "status", String.valueOf(response == null ? "-1" : response.code()),
                    "uri", URLUtil.getPath(request.url().toString()),
                    "async", async + ""
            );
            sample.stop(timer);
        }
        return response;
    }

}

整合 Grafana

采集到Prometheus的数据,可以通过界面操作,但如果想以仪表盘的直观形式展示更多指标信息,可以考虑整合Grafana,整合工作很简单,代码不需要任何改动。
只需要按如下步骤:

  • 安装并启动 Grafana。
  • 配置 Prometheus 数据源。
  • 创建或导入 Dashboard。
  • 使用 Prometheus 查询语法可视化指标。
  • 根据需要配置告警和通知。

企业微信截图_17089126918229.png
相关博文:《企业实战分享 · 常用运维中间件》


关于 PromQL 语法

使用Prometheus界面查询的时候,需要借助PromQL语法,一般使用Prometheus查询自定义指标。
通过指标建议通过Grafana面板查询更直观。
下方是一些查询示例:

语法:<metric name>{<label name>=<label value>, ...}
示例一:onelink_datasource_poolingCount{application="archive-service"}[20s] offset 1m
示例分析:
1、onelink_datasource_poolingCount是指标名称,是自定义指标,代表“当前连接池中的连接数”;
2、{application="archive-service"}大括号代表过滤,很好理解;
3、[20s]中括号代表时间范围,没添加时间的代表瞬时向量查询,添加了时间的代表区间向量查询,右侧Value会出现多个值,值的个数等于指定时间/拉取频率,例如开发库指定10秒拉取,则出现2个值。
4、offset代表时间位移,不添加代表以当前系统时间为基准进行查询;

示例二:
count(onelink_datasource_poolingCount{application="archive-service"} > 1)
rate(onelink_datasource_poolingCount{application="archive-service"}[1m]) --1分钟增长
topk(6, onelink_datasource_poolingCount > 3) -- 查看前6的指标
示例分析:
1、通过布尔运算对时间序列进行过滤,其实就是上面示例二的大于号,将value进行比对;
2、可以使用一些函数,具体看示例;

过滤符号补充:
label=value 完全匹配
label!=value 完全不陪陪
label=~regx 正则匹配
label=!~regx 正则不匹配
onelink_datasource_poolingCount{application=~"archive-service|dc-.*"}

时间单位补充:
s - 秒
m - 分钟
h - 小时
d - 天
w - 周
y - 年

布尔运算补充:
== (相等)
!= (不相等)
> (大于)
< (小于)
>= (大于等于)
<= (小于

推荐文章 - 程序猿入职必会:
《程序猿入职必会(1) · 搭建拥有数据交互的 SpringBoot 》
《程序猿入职必会(2) · 搭建具备前端展示效果的 Vue》
《程序猿入职必会(3) · SpringBoot 各层功能完善 》
《程序猿入职必会(4) · Vue 完成 CURD 案例 》
《程序猿入职必会(5) · CURD 页面细节规范 》
《程序猿入职必会(6) · 返回结果统一封装》
《程序猿入职必会(7) · 前端请求工具封装》
《程序猿入职必会(8) · 整合 Knife4j 接口文档》
《程序猿入职必会(9) · 用代码生成器快速开发》
《程序猿入职必会(10) · 整合 Redis(基础篇)》
《程序猿入职必会(11) · 整合 Redis 实战运用》

推荐文章 - 学会 SpringMVC 系列
《学会 SpringMVC 系列 · 基础篇》
《学会 SpringMVC 系列 · 剖析篇(上)》
《学会 SpringMVC 系列 · 剖析入参处理》
《学会 SpringMVC 系列 · 剖析出参处理》
《学会 SpringMVC 系列 · 返回值处理器》
《学会 SpringMVC 系列 · 消息转换器 MessageConverters》
《学会 SpringMVC 系列 · 写入拦截器 ResponseBodyAdvice》
《学会 SpringMVC 系列 · 剖析初始化》
《学会 SpringMVC 系列 · 参数解析器 ArgumentResolvers》

总结陈词

💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。

CSDN_END.gif

  • 15
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Prometheus 是一个开源的、分布式的时间序列数据库和监控系统,被广泛用于收集、存储和查询监控数据。它以其灵活的查询语言 PromQL 和强大的 Alertmanager 功能而闻名,常用于监控云原生应用和服务的性能和健康状况。 在企业实战中,Prometheus 可以应用于以下几个方面: 1. **数据采集**:Prometheus 支持各种插件(即 exporters)来收集来自不同服务(如 Node.js、Java、容器等)的监控指标。它可以直接从应用程序的日志中提取指标,或者通过标准协议(如 HTTP、TCP、gRPC)获取信息。 2. **灵活配置**:Prometheus 的 Scrape 命令允许自定义采集间隔和目标列表,可以适应复杂的微服务架构,轻松扩展到大规模环境。 3. **实时查询与可视化**:用户可以通过 PromQL 进行实时查询,生成丰富的仪表板和图形展示,帮助团队快速理解系统的运行状态。 4. **警报通知**:Alertmanager 可以根据预定义的规则触发警报,并通过邮件、Slack、PagerDuty 等多种渠道通知相关人员,提高响应速度。 5. **服务发现与容错**:Prometheus 提供了 Service Discovery 功能,即使服务的地址发生变化,也能够自动更新监控数据。 6. **高可用性**:企业级使用中,通常会通过集群部署和冗余策略提高 Prometheus 和 Alertmanager 的可用性和容错能力。 **相关问题--:** 1. 在企业级环境中,如何确保Prometheus的数据可靠性? 2. 如何在Prometheus中设置有效的警报规则以防止过度通知? 3. 当Prometheus遇到高负载时,有哪些优化策略?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

战神刘玉栋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值