jvm接入prometheus监控

  1. 创建以下两个配置类:
package com.haoze.doctor.config;
import com.alibaba.druid.pool.DruidDataSource;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.function.ToDoubleFunction;
@Component
public class DruidCollector {
    @Value("${spring.application.name}")
    private String applicationName;
    private static final String LABEL_NAME = "druid_pool";
    private final MeterRegistry registry;
    DruidCollector(MeterRegistry registry) {
        this.registry = registry;
    }
    void register(List<DruidDataSource> dataSources) {
        dataSources.forEach((druidDataSource) -> {
            // basic configurations
            createGauge(druidDataSource, "druid_initial_size", "Initial size", (datasource) -> (double) druidDataSource.getInitialSize());
            createGauge(druidDataSource, "druid_min_idle", "Min idle", datasource -> (double) druidDataSource.getMinIdle());
            createGauge(druidDataSource, "druid_max_active", "Max active", datasource -> (double) druidDataSource.getMaxActive());
            // connection pool core metrics
            createGauge(druidDataSource, "druid_active_count", "Active count", datasource -> (double) druidDataSource.getActiveCount());
            createGauge(druidDataSource, "druid_active_peak", "Active peak", datasource -> (double) druidDataSource.getActivePeak());
            createGauge(druidDataSource, "druid_pooling_peak", "Pooling peak", datasource -> (double) druidDataSource.getPoolingPeak());
            createGauge(druidDataSource, "druid_pooling_count", "Pooling count", datasource -> (double) druidDataSource.getPoolingCount());
            createGauge(druidDataSource, "druid_wait_thread_count", "Wait thread count", datasource -> (double) druidDataSource.getWaitThreadCount());
            // connection pool detail metrics
            createGauge(druidDataSource, "druid_not_empty_wait_count", "Not empty wait count", datasource -> (double) druidDataSource.getNotEmptyWaitCount());
            createGauge(druidDataSource, "druid_not_empty_wait_millis", "Not empty wait millis", datasource -> (double) druidDataSource.getNotEmptyWaitMillis());
            createGauge(druidDataSource, "druid_not_empty_thread_count", "Not empty thread count", datasource -> (double) druidDataSource.getNotEmptyWaitThreadCount());
            createGauge(druidDataSource, "druid_logic_connect_count", "Logic connect count", datasource -> (double) druidDataSource.getConnectCount());
            createGauge(druidDataSource, "druid_logic_close_count", "Logic close count", datasource -> (double) druidDataSource.getCloseCount());
            createGauge(druidDataSource, "druid_logic_connect_error_count", "Logic connect error count", datasource -> (double) druidDataSource.getConnectErrorCount());
            createGauge(druidDataSource, "druid_physical_connect_count", "Physical connect count", datasource -> (double) druidDataSource.getCreateCount());
            createGauge(druidDataSource, "druid_physical_close_count", "Physical close count", datasource -> (double) druidDataSource.getDestroyCount());
            createGauge(druidDataSource, "druid_physical_connect_error_count", "Physical connect error count", datasource -> (double) druidDataSource.getCreateErrorCount());
            // sql execution core metrics
            createGauge(druidDataSource, "druid_error_count", "Error count", datasource -> (double) druidDataSource.getErrorCount());
            createGauge(druidDataSource, "druid_execute_count", "Execute count", datasource -> (double) druidDataSource.getExecuteCount());
            // transaction metrics
            createGauge(druidDataSource, "druid_start_transaction_count", "Start transaction count", datasource -> (double) druidDataSource.getStartTransactionCount());
            createGauge(druidDataSource, "druid_commit_count", "Commit count", datasource -> (double) druidDataSource.getCommitCount());
            createGauge(druidDataSource, "druid_rollback_count", "Rollback count", datasource -> (double) druidDataSource.getRollbackCount());
            // sql execution detail
            createGauge(druidDataSource, "druid_prepared_statement_open_count", "Prepared statement open count", datasource -> (double) druidDataSource.getPreparedStatementCount());
            createGauge(druidDataSource, "druid_prepared_statement_closed_count", "Prepared statement closed count", datasource -> (double) druidDataSource.getClosedPreparedStatementCount());
            createGauge(druidDataSource, "druid_ps_cache_access_count", "PS cache access count", datasource -> (double) druidDataSource.getCachedPreparedStatementAccessCount());
            createGauge(druidDataSource, "druid_ps_cache_hit_count", "PS cache hit count", datasource -> (double) druidDataSource.getCachedPreparedStatementHitCount());
            createGauge(druidDataSource, "druid_ps_cache_miss_count", "PS cache miss count", datasource -> (double) druidDataSource.getCachedPreparedStatementMissCount());
            createGauge(druidDataSource, "druid_execute_query_count", "Execute query count", datasource -> (double) druidDataSource.getExecuteQueryCount());
            createGauge(druidDataSource, "druid_execute_update_count", "Execute update count", datasource -> (double) druidDataSource.getExecuteUpdateCount());
            createGauge(druidDataSource, "druid_execute_batch_count", "Execute batch count", datasource -> (double) druidDataSource.getExecuteBatchCount());
            // none core metrics, some are static configurations
            createGauge(druidDataSource, "druid_max_wait", "Max wait", datasource -> (double) druidDataSource.getMaxWait());
            createGauge(druidDataSource, "druid_max_wait_thread_count", "Max wait thread count", datasource -> (double) druidDataSource.getMaxWaitThreadCount());
            createGauge(druidDataSource, "druid_login_timeout", "Login timeout", datasource -> (double) druidDataSource.getLoginTimeout());
            createGauge(druidDataSource, "druid_query_timeout", "Query timeout", datasource -> (double) druidDataSource.getQueryTimeout());
            createGauge(druidDataSource, "druid_transaction_query_timeout", "Transaction query timeout", datasource -> (double) druidDataSource.getTransactionQueryTimeout());
        });
    }
    private void createGauge(DruidDataSource weakRef, String metric, String help, ToDoubleFunction<DruidDataSource> measure) {
        Gauge.builder(metric, weakRef, measure)
                .description(help)
                .tag(LABEL_NAME, weakRef.getUsername() + "-" + weakRef.getUrl())
                .tag("application", applicationName)
                .register(this.registry);
    }
}

package com.haoze.doctor.config;
import com.alibaba.druid.pool.DruidDataSource;
import io.micrometer.core.instrument.MeterRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Configuration
@ConditionalOnClass({DruidDataSource.class, MeterRegistry.class})
@Slf4j
public class MetricsConfiguration {
    @Value("${spring.application.name}")
    private String applicationName;
    private final MeterRegistry registry;
    @Autowired
    private DruidCollector druidCollector;
    public MetricsConfiguration(MeterRegistry registry) {
        this.registry = registry;
    }
    @Bean
    MeterRegistryCustomizer<MeterRegistry> configurer() {
        return (registry) -> registry.config().commonTags("application", applicationName);
    }
    @Autowired
    public void bindMetricsRegistryToDruidDataSources(Collection<DataSource> dataSources) throws SQLException {
        List<DruidDataSource> druidDataSources = new ArrayList<>(dataSources.size());
        for (DataSource dataSource : dataSources) {
            DruidDataSource druidDataSource = dataSource.unwrap(DruidDataSource.class);
            if (druidDataSource != null) {
                druidDataSources.add(druidDataSource);
            }
        }
//        DruidCollector druidCollector = new DruidCollector(druidDataSources, registry);
        druidCollector.register(druidDataSources);
        log.info("finish register metrics to micrometer");
    }
}

  1. pom文件中的druid版本需要在这个以上:
     <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>druid</artifactId>
         <version>1.1.14</version>
     </dependency>

其他需要引入的maven依赖:

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-actuator</artifactId>
     </dependency>
     <dependency>
         <groupId>io.micrometer</groupId>
         <artifactId>micrometer-registry-prometheus</artifactId>
     </dependency>
     <!-- micrometer获取JVM相关信息,并展示在Grafana上 -->
     <dependency>
         <groupId>io.github.mweirauch</groupId>
         <artifactId>micrometer-jvm-extras</artifactId>
         <version>0.2.2</version>
     </dependency>
  1. actuator配置需要支持prometheus
management:
endpoints:
 web:
   exposure:
     include: "httptrace,health,shutdown,prometheus"
 shutdown:
   enabled: true
 health:
   show-details: ALWAYS
  1. 本地验证:
    在这里插入图片描述5. 对于普通的部署方式,到这一步之后,我们直接到prometheus上去配置ip和端口就可以实现监控了,像下面这样在prometheus.yml配置文件中进行配置,并重启服务prometheus服务即可。
    #新增jvm监控任务  
  - job_name: "jvm"
    # 采集数据间隔时间
    scrape_interval: 5s
    # 采集时的超时时间
    scrape_timeout: 5s
    # 采集数据的路径
    metrics_path: '/actuator/prometheus'
    # 应用服务的地址
    static_configs:
      - targets: ['169.169.169.98:8203']
  1. 但对于容器化部署,这种ip会变的场景下,需要借助prometheus的注册发现来实现了,比如这里我们通过nacos注册发现。nacos的application.properties文件中进行修改,修改后重启nacos服务
## 配置设置为true
nacos.prometheus.metrics.enabled=true

然后可以通过 http://ip:8848/nacos/prometheus/,查看注册内容。
6. prometheus配置自动发现。修改prometheus的prometheus.yml,添加以下内容:

   - job_name: 'prod-jvm'
     metrics_path: /actuator/prometheus
     scheme: http
     http_sd_configs:
      ## namespaceId/prod 表示指定prod这个命名空间下的
      ## 如果不指定命名空间,可以省去这部分,直接:http://ip:8848/nacos/prometheus/
     - url: http://ip:8848/nacos/prometheus/namespaceId/prod
<think>好的,我需要帮助用户将他们的Java项目接入Prometheus监控。首先,我要回忆一下Prometheus的基本工作原理,它主要是通过HTTP端点拉取指标数据,所以用户需要在Java应用中暴露一个供Prometheus抓取的端点。 接下来,我应该考虑常用的Java客户端库,比如Prometheus提供的官方客户端simpleclient。可能需要提到添加Maven或Gradle依赖,例如io.prometheus的依赖项。 然后,用户需要在自己的代码中定义指标,比如计数器、直方图等,并在适当的地方进行指标记录。例如,使用Counter来统计请求次数,Gauge来监控实时数据,Histogram来跟踪请求延迟等。 接下来,需要配置一个HTTP服务器来暴露指标端点,通常使用内置的HTTPServer或者整合到现有的Web框架中,比如Spring Boot的Actuator。这里可能需要详细说明如何创建HTTP端点,比如在特定端口上启动一个服务器,并将指标数据暴露在/metrics路径下。 然后,Prometheus的配置部分需要编辑prometheus.yml文件,添加对应的抓取目标,指定Java应用的IP和端口,以及抓取间隔等参数。这部分可能需要给出一个配置示例,确保用户能够正确修改他们的Prometheus配置。 另外,可能需要提到与Spring Boot的集成,使用Micrometer作为门面,通过Micrometer Prometheus registry来简化配置。这样用户如果已经在使用Spring Boot,可以更方便地集成Prometheus监控。 还要考虑一些高级功能,比如自定义指标标签,或者使用Grafana进行可视化,但可能这些是后续步骤,用户现阶段可能只需要基础接入。不过可以简要提及,作为扩展建议。 最后,验证步骤,启动应用和Prometheus后,如何通过Prometheus的Web界面检查目标状态是否正常,并查询指标确认数据是否正确收集。如果有问题,可能需要检查端口是否开放,配置是否正确,或者应用是否成功注册指标。 需要确保步骤清晰,避免技术术语过于复杂,让用户能够一步步跟着操作。同时注意可能的常见错误,比如依赖版本冲突,端点路径错误,Prometheus配置错误等,可以适当给出排查建议。 总结下来,回答的结构应该是:引入Prometheus和Java客户端库,添加依赖,定义指标,暴露端点,配置Prometheus,验证和扩展建议。需要分步骤说明,每部分给出代码示例和配置示例,确保用户能够实际操作。</think>以下是Java项目接入Prometheus监控的分步指南,涵盖依赖配置、指标暴露、数据抓取及可视化全流程: --- ### **1. 核心依赖** 在`pom.xml`中添加Prometheus Java客户端库: ```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. 定义监控指标** 在代码中声明需要收集的指标(如计数器、直方图): ```java import io.prometheus.client.*; // 定义请求计数器(带标签) static final Counter requests = Counter.build() .name("http_requests_total") .help("Total HTTP requests.") .labelNames("method", "path") .register(); // 定义请求耗时直方图(单位:秒) static final Histogram requestLatency = Histogram.build() .name("http_request_duration_seconds") .help("HTTP request latency in seconds.") .buckets(0.1, 0.5, 1.0) // 自定义分桶范围 .register(); ``` --- ### **3. 暴露指标端点** 启动HTTP服务器暴露`/metrics`接口(默认端口:`9091`): ```java public class PrometheusExporter { public static void main(String[] args) throws IOException { // 启动内置HTTP服务器 HTTPServer server = new HTTPServer(9091); // 示例:记录一个请求指标 requests.labels("GET", "/api/data").inc(); requestLatency.labels("/api/data").observe(0.23); } } ``` --- ### **4. Prometheus配置** 修改`prometheus.yml`,添加抓取目标: ```yaml scrape_configs: - job_name: 'java_app' scrape_interval: 15s # 抓取频率 static_configs: - targets: ['localhost:9091'] # 替换为实际IP和端口 ``` --- ### **5. 与Spring Boot集成(可选)** 若使用Spring Boot,可结合`Micrometer`简化配置: ```xml <!-- pom.xml --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> <version>1.10.0</version> </dependency> ``` 配置`application.properties`: ```properties management.endpoints.web.exposure.include=prometheus,health,metrics management.server.port=8081 # 指定Actuator端口 ``` --- ### **6. 验证与查询** 1. 启动应用和Prometheus服务 2. 访问 `http://localhost:9090/targets` 检查目标状态是否为**UP** 3. 在Prometheus控制台输入查询语句(如 `http_requests_total`) --- ### **7. 可视化(Grafana)** 1. 安装Grafana并添加Prometheus数据源 2. 导入官方提供的[JVM监控仪表盘](https://grafana.com/grafana/dashboards/4701)(ID: 4701) 3. 自定义图表展示核心指标(如QPS、错误率、JVM内存) --- ### **常见问题排查** | 问题现象 | 解决方法 | |---------|----------| | `/metrics`返回404 | 检查HTTP服务器是否启动,端口是否冲突 | | Prometheus无法连接 | 确认防火墙规则,检查`targets`配置的IP和端口 | | 指标数据不更新 | 验证代码中指标是否被正确调用(如`inc()`或`observe()`) | 如果需要更详细的代码示例或特定场景(如分布式追踪),可进一步补充说明!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值