Java获取Prometheus监控指标数据

一. 准备工作

1. 有可以被Prometheus监控的服务

没有的话可以参考以下链接本地搭建:SpringBoot应用接入Prometheus+Grafana

2. 选择我们调用远程服务的方式

可以选择RestTemplate 作为远程调用工具,RestTemplate 内部默认用的是 jdk 自带的
HttpURLConnection 发送请求的,性能上面并不是太突出。可以将其替换为 httpclient 或者 okhttp。

二. 实战

1. 引入依赖

   <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency>

2. 编写http请求工具

package com.alibaba.bizworks.om.account.prometheus;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.client.HttpClient;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;/*** RestTemplate 远程调用工具类* @author gf* @date 2022/10/24*/
@Slf4j
public class RestTemplateUtils {/*** 读取时间,自定义默认8s,0表示没有超时时间*/public static final int READ_TIMEOUT = 1000*8;/*** 连接时间,自定义默认8s,0表示没有超时时间*/public static final int CONNEC_TIMEOUT = 1000*8;/*** 重试次数,自定义默认1*/public static final int RETRY_COUNT = 1;/*** http 请求 GET** @param url           地址* @param params        参数* @return String 类型*/public static String getHttp(String url, JSONObject params) {String result = getHttp(url, params, READ_TIMEOUT, CONNEC_TIMEOUT, RETRY_COUNT);return result;}/*** http 请求 GET** @param url           地址* @param params        参数* @param connecTimeout 连接时间* @param readTimeout   读取时间* @param retryCount    重试机制* @return String 类型*/public static String getHttp(String url, JSONObject params, int connecTimeout, int readTimeout, int retryCount) {SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();requestFactory.setConnectTimeout(connecTimeout);requestFactory.setReadTimeout(readTimeout);RestTemplate restTemplate = new RestTemplate(requestFactory);restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); // 设置编码集restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); // 异常处理url = expandURL(url, params);String result = null; // 返回值类型;for (int i = 1; i <= retryCount; i++) {try {log.info("【GET/HTTP请求信息】,请求地址:{},请求参数:{}", url, params);result = restTemplate.getForObject(url, String.class, params);log.info("【GET/HTTP请求信息】,请求地址:{},请求参数:{},返回结果:{}", url, params,result);return result;} catch (Exception e) {log.error("【GET/HTTP请求信息】异常,重试count:{},请求地址:{},请求参数:{},异常信息:{}", i, url, params,e);e.printStackTrace();}}return result;}/*** https 请求 GET** @param url           地址* @param params        参数* @return String 类型*/public static String getHttps(String url, JSONObject params) {String result = getHttps(url, params, READ_TIMEOUT, CONNEC_TIMEOUT, RETRY_COUNT);return result;}/*** https 请求 GET** @param url           地址* @param params        参数* @param connecTimeout 连接时间* @param readTimeout   读取时间* @param retryCount    重试机制* @return String 类型*/public static String getHttps(String url, JSONObject params, int connecTimeout, int readTimeout, int retryCount) {SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();requestFactory.setConnectTimeout(connecTimeout);requestFactory.setReadTimeout(readTimeout);RestTemplate restTemplate = restTemplate();RestTemplateUtils.clientHttpRequestFactory();restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); // 设置编码集restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); //error处理restTemplate.setRequestFactory(clientHttpRequestFactory()); // 绕过httpsurl = expandURL(url, params);String result = null; // 返回值类型;for (int i = 1; i <= retryCount; i++) {try {log.info("【GET/HTTPS请求信息】,请求地址:{},请求参数:{}", url, params);result = restTemplate.getForObject(url, String.class, params);log.info("【GET/HTTPS请求信息】,请求地址:{},请求参数:{},返回结果:{}", url, params,result);return result;} catch (Exception e) {log.error("【GET/HTTPS请求信息】异常,重试count:{},请求地址:{},请求参数:{},异常信息:{}", i, url, params,e);e.printStackTrace();}}return result;}/*** @Title: URL拼接* @MethodName:  expandURL* @param url* @param jsonObject* @Return java.lang.String* @Exception* @Description:*/private static String expandURL(String url,JSONObject jsonObject) {StringBuilder sb = new StringBuilder(url);sb.append("?");Set<String> keys = jsonObject.keySet();for (String key : keys) {sb.append(key).append("=").append(jsonObject.getString(key)).append("&");}return sb.deleteCharAt(sb.length() - 1).toString();}/*** 获取RestTemplate实例对象,可自由调用其方法** @return RestTemplate实例对象*/public static HttpClient httpClient() {HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();try {//设置信任ssl访问SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (arg0, arg1) -> true).build();httpClientBuilder.setSSLContext(sslContext);HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()// 注册http和https请求.register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslConnectionSocketFactory).build();//使用Httpclient连接池的方式配置(推荐),同时支持netty,okHttp以及其他http框架PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);// 最大连接数poolingHttpClientConnectionManager.setMaxTotal(1000);// 同路由并发数poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100);//配置连接池httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);// 重试次数httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(1, true));//设置默认请求头List<Header> headers = new ArrayList<>();httpClientBuilder.setDefaultHeaders(headers);return httpClientBuilder.build();} catch (Exception e) {throw new RuntimeException(e);}}public static ClientHttpRequestFactory clientHttpRequestFactory() {HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient());// 连接超时(毫秒),这里设置10秒clientHttpRequestFactory.setConnectTimeout(10 * 1000);// 数据读取超时时间(毫秒),这里设置60秒clientHttpRequestFactory.setReadTimeout(60 * 1000);// 从连接池获取请求连接的超时时间(毫秒),不宜过长,必须设置,比如连接不够用时,时间过长将是灾难性的clientHttpRequestFactory.setConnectionRequestTimeout(10 * 1000);return clientHttpRequestFactory;}public static RestTemplate restTemplate(){//创建RestTemplate的时候,指定ClientHttpRequestFactoryreturn new RestTemplate(clientHttpRequestFactory());}}

3. 编写响应体

从浏览器中找到peomrtheus它获取服务指标的请求地址

然后根据这个地址在postman发get请求拿到它的响应体结构

接下来我们就可以根据这个结果来封装相应体了

@Data
public class PromResponceInfo {/*** 状态* 成功-- success*/private String status;/*** prometheus指标属性和值*/private PromDataInfo data;}

这里只关注后面的resultType 和result参数

@Data
public class PromDataInfo {/*** prometheus监控服务指表参数*/private List droppedTargets;private List<PromResultInfo> activeTargets;/*** prometheus监控样本指标参数*/private String resultType;private List<PromMetric> result;}
@Data
public class PromMetric {/*** metric name和描述当前样本特征的labelsets*/private PromMetricInfo metric;/*** 一个float64的浮点型数据表示当前样本的值。*/private String[] value;}
@Data
public class PromMetricInfo {/*** prometheus指标名称*/private String __name__;/*** prometheus实例名称*/private String instance;/*** prometheus任务名称*/private String job;private String application;private String exception;private String method;private String outcome;private String status;private String url;
}
/*** prometheus服务指标参数* @author gf* @date 2022/10/19*/
@Data
public class PromResultInfo {/*** prometheus指标属性*/private PromMetricInfo labels;/*** prometheus指标值*/private String globalUrl;private String health;private String lastScrape;private String lastScrapeDuration;private String scrapeInterval;private String scrapePool;private String scrapeTimeout;private String scrapeUrl;}

到这里我们响应体的结构就写好了,还有一个指标参数,我这里写了一个类,后面需要查询指标或者一些聚合函数(PromQL)

package com.alibaba.bizworks.om.account.prometheus;import lombok.Data;/*** @Title: prometheus常量信息* @author gf* @date 2022/10/19*/
@Data
public class PromConstants {/*** prometheus-查询SUCCESS*/public static final String SUCCESS = "success";/**prometheus-查询参数*/public static final String QUERY = "query";/**系统CPU使用率*/public static final String SYSTEM_CPU_USAGE= "system_cpu_usage";/**Java虚拟机可用的处理器数量*/public static final String SYSTEM_CPU_COUNT= "system_cpu_count";/**JVM的CPU利用率*/public static final String PROCESS_CPU_COUNT= "process_cpu_usage";/***  tomcat相关参数*//**tomcat_当前活跃会话数*/public static final String TOMCAT_SESSIONS_ACTIVE_CURRENT_SESSIONS = "tomcat_sessions_active_current_sessions";/***  jvm 相关参数*//**Java虚拟机的正常运行时间*/public static final String PROCESS_UPTIME_SECONDS = "process_uptime_seconds";/**可供Java虚拟机使用的已提交的内存量*/public static final String JVM_MEMORT_COMMITTED_BYTES = "jvm_memory_committed_bytes";/**自Java虚拟机启动或重置峰值以来的活动线程峰值*/public static final String JVM_THREADS_PEAK_THREADS= "jvm_threads_peak_threads";/**在一个GC之后到下一个GC之前增加年轻代内存池的大小*/public static final String JVM_GC_MEMORT_ALLOCATED_BYTES_TOTAL= "jvm_gc_memory_allocated_bytes_total";/**进程的开始时间*/public static final String PROCESS_START_TIME_SECONDS= "process_start_time_seconds";/**最大内存*/public static final String JVM_MEMORT_MAX_BYTES= "jvm_memory_max_bytes";/**已使用内存*/public static final String JVM_MEMORT_USED_BYTES= "jvm_memory_used_bytes";/**请求次数*/public static final String HTTP_SERVER_REQUEST_SECONDS_COUNT= "http_server_requests_seconds_count";/**请求n次花费的时间*/public static final String HTTP_SERVER_REQUEST_SECONDS_SUM= "http_server_requests_seconds_sum";/**最长一次花了多长时间*/public static final String HTTP_SERVER_REQUEST_SECONDS_MAX= "http_server_requests_seconds_max";/**日志总数*/public static final String LOGBACK_EVENTS_TOTAL = "logback_events_total";}

4. 编写接口测试

参数说明:

  • promURL:请求url
  • promQL:指标参数
@Slf4j
public class TestController {public static PromDataInfo getDateInfo(String promURL, String promQL) {log.info("请求地址:{},请求QL:{}", promURL, promQL);JSONObject param = new JSONObject();param.put(PromConstants.QUERY, promQL);String http = null;try {http = RestTemplateUtils.getHttp(promURL, param);} catch (Exception e) {log.error("请求地址:{},请求QL:{},异常信息:{}", promURL, promQL, e);}PromResponceInfo responceInfo = JSON.parseObject(http, PromResponceInfo.class);log.info("请求地址:{},请求QL:{},返回信息:{}", promURL, promQL, responceInfo);if (Objects.isNull(responceInfo)) {return null;}String status = responceInfo.getStatus();if (StringUtils.isBlank(status)|| !PromConstants.SUCCESS.equals(status)) {return null;}PromDataInfo data = responceInfo.getData();return data;}public static void main(String[] args) {PromDataInfo dateInfo= getDateInfo("http://localhost:9090/api/v1/query", PromConstants.HTTP_SERVER_REQUEST_SECONDS_COUNT);System.out.println(dateInfo);}
}

5. 测试结果

我们可以debug查看获取到的信息

Java获取Prometheus监控指标数据相关推荐

  1. 【kafka 监控】Kafka_exporter+prometheus 监控kafka数据

    一.kafka_exporter 安装步骤: Kafka_exporter是一款用于将Kafka集群的监控指标暴露给Prometheus的开源工具,可以用于监控Kafka集群的各种状态数据.下面是Ka ...

  2. 实战|如何优雅地自定义Prometheus监控指标

    今天要和大家分享的是在实际工作中**"如何优雅地自定义Prometheus监控指标"**!目前大部分使用Spring Boot构建微服务体系的公司,大都在使用Prometheus来 ...

  3. MongoDB学习笔记(四)使用Java进行实时监控与数据收集(空间使用量、连接数)

    目录: MongoDB学习笔记(一)环境搭建与常用操作 MongoDB学习笔记(二)使用Java操作MongoDB MongoDB学习笔记(三)使用Spring Data操作MongoDB Mongo ...

  4. java 获取nodejs端Gson数据案例(请求MongoDB)

    java  获取nodejs端Gson数据案例 原理:这是一个demo,主要通过java向nodejs端发送请求,nodejs端向mongodb请求数据,并将请求的数据以Gson的格式返回给java端 ...

  5. JAVA获取excel第一列数据

    JAVA获取excel第一列数据 提示 1:需要将.xlsx格式转为.xls(不懂得自行百度) 2:不要一次读取太多数据,导致内存溢出 一个简单的方法========== @GetMapping(&q ...

  6. java结合prometheus实现自定义数据监控

    一.配置prometheus prometheus.yml ...- job_name: 'my-service'metrics_path: /metricsstatic_configs:- targ ...

  7. java获取xlsx某列数据_Java读取Excel指定列的数据详细教程和注意事项

    本文使用jxl.jar工具类库实现读取Excel中指定列的数据. jxl.jar是通过java操作excel表格的工具类库,是由java语言开发而成的.这套API是纯Java的,并不依赖Windows ...

  8. python获取财务数据曝光_Python-股票-从网易财经获取主要财务指标数据

    以下代码从网易财经的个股页面获取主要财务指标,获取的数据输出到Excel电子表格中. import pandas as pd from pandas.core.frame import DataFra ...

  9. Python-股票-从网易财经获取主要财务指标数据

    以下代码从网易财经的个股页面获取主要财务指标,获取的数据输出到Excel电子表格中. import pandas as pd from pandas.core.frame import DataFra ...

最新文章

  1. FileMaker中的腳本觸發器學習筆記
  2. Android:手把手教你 实现Activity 与 Fragment 相互通信(含Demo)
  3. 用DirectoryInfo搜索文件夹时过滤隐藏文件夹
  4. linux 复制栈数据结构,算法-数据结构-堆栈
  5. c语言枚举入门,C语言入门之枚举与位运算(1)
  6. php html区别_php与html区别
  7. 用ibatis.net简单的数据更新
  8. 北京可以备案什么域名
  9. java cookie过期_在Express中,会话Cookie过期
  10. 在windows Console 平台下面 用glut编写 opengl程序 注意
  11. html坦克游戏,HTML5实现经典坦克大战坦克乱走还能发出一个子弹
  12. svchost.exe病毒-任务栏怎么也关闭不掉的搜索框
  13. Mac电脑为什么适合编程?
  14. sass安装步骤、概述、基本语法等
  15. 前后端交互之form表单和模板引擎
  16. 必应搜索 - 显示历史记录
  17. 中国版权力的游戏构思
  18. QUICK PCB抄板教程(无网络编号)
  19. json对象与json字符串互转,ajax各常见函数
  20. 针对 Telnet 协议的威胁观察

热门文章

  1. 创业日志(十二) 关于怠惰
  2. 分布式存储系统设计 反熵 (Anti-Entropy)
  3. 实现类似微信视频聊天的功能
  4. tableau函数与计算之二(表计算)
  5. 为什么要用 picture 标签代替 img 标签?
  6. ACM省赛及蓝桥总结,且随疾风前行,身后亦须留心
  7. 入住阿里云MQTT物联网平台
  8. Bzoj1823 [JSOI2010]满汉全席
  9. mfc editctrl限制输入
  10. html怎么取消转义字符,正确取消html字符的转义