如何为你的Spring Boot应用装上一个功能强大的监控仪表盘

在现代微服务架构中,系统监控已成为保障应用稳定性的关键环节。通过有效的监控,我们可以实时了解应用的运行状态,及时发现并解决性能问题。本文将介绍如何使用Micrometer及其注册表(Registry)在Spring Boot环境中实现全面系统参数监控。

1 Micrometer简介

Micrometer是一款供应商中立的应用程序指标门面(Facade),类似于SLF4J在日志领域的作用,它为不同监控系统提供了统一的度量采集API。它可以与多种监控系统(如Prometheus、Datadog、New Relic、InfluxDB等)无缝集成,让你无需修改代码即可切换监控后端。

Micrometer的架构围绕三个核心概念构建:

  • Meter:表示具体的度量指标,如计数器(Counter)、计时器(Timer)等

  • MeterRegistry:负责创建和存储Meter的核心接口

  • Binder:将框架内部指标(如JVM指标)自动绑定到注册表

2 Spring Boot集成Micrometer

2.1 添加依赖

首先,在您的pom.xml中添加以下依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency><groupId>io.micrometer</groupId><artifactId>micrometer-core</artifactId>
</dependency>
<!-- 使用Prometheus作为监控系统 -->
<dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

如果使用Gradle,可以在build.gradle中添加:

implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-core'
implementation 'io.micrometer:micrometer-registry-prometheus'

2.2 配置监控端点

application.ymlapplication.properties中进行配置:

management:endpoints:web:exposure:include: health,info,metrics,prometheusmetrics:tags:application: ${spring.application.name}region: northexport:prometheus:enabled: true

此配置开启了Actuator的监控端点,并设置了全局标签(application和region),这些标签会附加到所有监控指标上

2.3 选择监控系统

Micrometer支持多种监控系统,以下是常见选择:

监控系统适用场景特点
Prometheus时间序列监控开源、拉取模式、适合Kubernetes环境
InfluxDB处理大量时间序列数据高性能、支持类SQL查询
Datadog全栈可观测性商业化、功能全面、支持多种数据源
StatsD简单指标收集轻量级、推送模式、易于部署

3 使用MeterRegistry记录指标

Spring Boot会自动配置一个MeterRegistry实例,可以直接在代码中使用它来记录各种指标。

3.1 计数器(Counter)

计数器用于记录单调递增的指标,如请求总数、订单创建数量等。

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;@Service
public class OrderService {private final Counter orderCounter;public OrderService(MeterRegistry meterRegistry) {this.orderCounter = meterRegistry.counter("orders.total", "type", "created");}public void createOrder() {// 业务逻辑orderCounter.increment();}
}

3.2 计量仪(Gauge)

Gauge用于测量瞬时值,如内存使用量、缓存大小等。

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.util.concurrent.atomic.AtomicInteger;@Component
public class MyGaugeComponent {private AtomicInteger myValue = new AtomicInteger(0);private final MeterRegistry meterRegistry;public MyGaugeComponent(MeterRegistry meterRegistry) {this.meterRegistry = meterRegistry;}@PostConstructpublic void init() {Gauge.builder("my_custom_gauge", myValue, AtomicInteger::get).description("A custom gauge example").tags("component", "gauge").register(meterRegistry);}public void updateValue(int newValue) {myValue.set(newValue);}@Beanpublic CommandLineRunner bindThreadPoolToMetrics(MeterRegistry registry,@Qualifier("asyncExecutorService") ThreadPoolTaskExecutor executor,SystemStatusService systemStatusService) {Gauge.builder("system.status.code", systemStatusService::getStatusCode).description("当前系统状态码").register(registry);return args -> {registry.gauge("asyncExecutorService.threadpool.core.size", executor, ThreadPoolTaskExecutor::getCorePoolSize);registry.gauge("asyncExecutorService.threadpool.max.size", executor, ThreadPoolTaskExecutor::getMaxPoolSize);registry.gauge("asyncExecutorService.threadpool.pool.size", executor, ThreadPoolTaskExecutor::getPoolSize);registry.gauge("asyncExecutorService.threadpool.active.count", executor, ThreadPoolTaskExecutor::getActiveCount);registry.gauge("asyncExecutorService.threadpool.queue.size", executor,new ToDoubleFunction<ThreadPoolTaskExecutor>() {@Overridepublic double applyAsDouble(ThreadPoolTaskExecutor value) {return value.getThreadPoolExecutor().getQueue().size();}});//registry.gauge("system.status.code", systemStatusService, SystemStatusService::getStatusCode);};}@Bean(name = "threadPoolTaskScheduler")public ThreadPoolTaskScheduler threadPoolTaskScheduler() {ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();executor.setPoolSize(2);executor.setThreadNamePrefix("TST-SCHEDULER");executor.setWaitForTasksToCompleteOnShutdown(true);executor.setAwaitTerminationSeconds(10);return executor;}
}

3.3 计时器(Timer)

计时器用于测量短时任务的持续时间,内置百分位计算。

import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;@Service
public class ApiService {private final Timer apiTimer;public ApiService(MeterRegistry meterRegistry) {this.apiTimer = meterRegistry.timer("api.requests", "api_type", "external");}public String callExternalApi() {return apiTimer.record(() -> {// 模拟API调用try {Thread.sleep(100);} catch (InterruptedException e) {Thread.currentThread().interrupt();}return "API response";});}
}

3.4 分布摘要(DistributionSummary)

分布摘要用于记录值的分布情况,适用于不涉及时间的测量,如响应体大小。

import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;@Service
public class ResponseService {private final DistributionSummary responseSizeSummary;public ResponseService(MeterRegistry meterRegistry) {this.responseSizeSummary = DistributionSummary.builder("response.size").description("Response size distribution").baseUnit("bytes").register(meterRegistry);}public void processResponse(String response) {// 记录响应大小responseSizeSummary.record(response.getBytes().length);}
}

4 监控HTTP请求

Spring Boot会自动监控HTTP请求,并提供一些默认的Metrics,如请求数量、响应时间等。您可以通过以下配置自定义这些指标:

management:metrics:web:server:request:autotime:enabled: truemetric:name: http.server.requests

还可以通过自定义过滤器来增强HTTP监控:

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Component
public class MetricFilter extends OncePerRequestFilter {private final MeterRegistry meterRegistry;public MetricFilter(MeterRegistry meterRegistry) {this.meterRegistry = meterRegistry;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String path = request.getRequestURI();String method = request.getMethod();meterRegistry.counter("http.requests.total", "method", method, "path", path).increment();long start = System.currentTimeMillis();try {filterChain.doFilter(request, response);} finally {long duration = System.currentTimeMillis() - start;meterRegistry.timer("http.requests.duration","method", method,"path", path,"status", String.valueOf(response.getStatus())).record(duration, TimeUnit.MILLISECONDS);}}
}

5 自定义MeterFilter

MeterFilter允许您修改或过滤Metrics。例如,可以重命名Metrics,或删除一些不必要的Metrics。

import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.MeterFilter;
import io.micrometer.core.instrument.config.MeterFilterReply;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MicrometerConfig {@Beanpublic MeterFilter renameFilter() {return MeterFilter.renameTag("http.server.requests", "method", "http_method");}@Beanpublic MeterFilter ignoreTagFilter() {return MeterFilter.ignoreTag("uri");}@Beanpublic MeterFilter denyFilter() {return MeterFilter.deny(id -> {String meterName = id.getName();// 拒绝以"temp"开头的指标return meterName != null && meterName.startsWith("temp");});}
}

6 查看监控数据

启动Spring Boot应用后,您可以访问/actuator/prometheus端点查看Prometheus格式的监控数据。

示例输出

# HELP jvm_memory_used_bytes The amount of used memory
# TYPE jvm_memory_used_bytes gauge
jvm_memory_used_bytes{application="my-app",area="heap",id="Eden Space",} 1.2632928E7

7 常见问题与解决方案

  1. Metric名称冲突
    如果应用中使用了多个库,它们都使用了相同的Metric名称,可能会导致冲突。解决这个问题的方法是使用不同的标签来区分这些Metrics。

  2. 性能问题
    如果应用需要记录大量的Metrics,可能会导致性能问题。解决这个问题的方法是减少Metrics的数量,或者使用更高效的监控系统。

  3. 数据丢失
    如果监控系统出现故障,可能会导致数据丢失。解决这个问题的方法是使用高可用的监控系统,并定期备份数据。

  4. 指标基数爆炸
    避免使用高基数的标签(如用户ID),这会导致指标数量急剧增加,影响监控系统性能。

8 最佳实践

  1. 标签设计:使用有限且一致的标签值集合,避免高基数标签。

  2. 命名规范:使用"."分隔小写单词字符,Micrometer会自动转换为各监控系统适应的格式。

  3. 监控策略:只监控关键指标,避免过度监控导致系统负载过重。

  4. 异常处理:确保指标记录不会影响主要业务逻辑,妥善处理异常。

  5. 文档化:为自定义指标提供清晰的文档说明,包括指标名称、标签含义和预期值范围。

9 总结

通过Spring Boot集成Micrometer,我们可以为应用快速添加一个功能强大的"监控仪表盘",实时了解应用的各项指标,如CPU使用率、内存占用、请求响应时间等。Micrometer作为监控门面,让我们能够灵活选择监控后端,而无需修改代码。

关键要点

  • Micrometer提供与供应商无关的监控指标接口

  • Spring Boot自动配置简化了集成过程

  • 合理使用标签和命名规范避免常见问题

  • 结合Grafana等可视化工具可以更好地展示监控数据

通过本文介绍的方法,我们可以快速为Spring Boot应用添加监控功能,及时发现并解决性能问题,确保应用的稳定性和可靠性。

彩蛋

监控参数使用prometheus+grafana展示出来,如下图所示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/923652.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/923652.shtml
英文地址,请注明出处:http://en.pswp.cn/news/923652.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【运维】-- 前端会话回放与产品分析平台之 openreplay

目录 OpenReplay 项目分析 1、项目概览 2、关键特性 3、代码结构&#xff08;Monorepo&#xff09; 4、技术栈与语言占比 5、部署与交付 6、社区与支持 7、版本与活跃度&#xff08;截至仓库页面所示&#xff09; 8、适用场景 9、优势与注意事项 10、落地建议&#…

NineData社区版 V4.5.0 正式发布!运维中心新增细粒度任务权限管理,新增MySQL至Greenplum全链路复制对比

NineData 社区版 V4.5.0 正式发布&#xff01;在数据复制方面&#xff0c;新增 MySQL 至 Greenplum 全链路复制对比&#xff0c;并优化全局 DDL 管控、MySQL/PostgreSQL/MongoDB 同构性能。在数据库 DevOps 方面&#xff0c;新增支持 AWS RDS 全系列及阿里云 PolarDB&#xff0…

discuz所有下载版本和升级工具

下载版本: Discuz! 每日构建版下载 - DiscuzX 3.x Daily Build Download Site SC是简体中文 TC是繁体中文 可能你需要其他版本: Discuz!官方网站 - 开放、连接、共赢 下载简体中文就好。 升级工具: 升级程序下载地址 https://gitee.com/oldhuhu/DiscuzX34235.git(…

【开题答辩全过程】以 “红色枣庄”旅游网站为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

【LeetCode】2785. 将字符串中的元音字母排序

题目描述 题目链接 问题分析 这道体的思路非常简单和好理解&#xff0c;找出字符串中的元音字符&#xff0c;然后按照ASSIC值进行排序&#xff0c;然后插入回对应的位置&#xff0c;解题步骤为&#xff1a; 使用一个set&#xff08;可以快速查找的容器&#xff09;&#x…

3 步发 10 亿邮件,这个 GitHub 开源项目牛逼。

你是否要经常批量发邮件&#xff1f;无论是向客户推送最新资讯、产品营销&#xff0c;还是发送日常常规通知类邮件。使用第三方邮件服务平台不仅成本高昂&#xff0c;功能限制多&#xff0c;而且可能无法保证隐私和安全。现在&#xff0c;有一个完全开源、能自己部署的解决方案…

【计算机网络】DNS 解析 DNS 污染

1. DNS 解析&#xff08;工作流程、参与方与缓存&#xff09; DNS 的目标&#xff1a;把人类可读的域名&#xff08;如 www.example.com&#xff09;映射为 IP 地址&#xff08;如 93.184.216.34&#xff09;。 典型解析流程&#xff08;递归解析器 迭代查询&#xff09;&…

用住宿楼模型彻底理解Kubernetes架构(运行原理视角)

导读&#xff1a;从楼宇建设到租客入住的全流程想象我们正在建设一栋巨型智能住宿楼&#xff0c;从基础设施搭建到租客入住管理&#xff0c;每个环节都对应Kubernetes的组件和概念。本文将按运行原理的先后顺序&#xff0c;系统解析Kubernetes的23个核心组件与基本概念。把 Kub…

嘉银科技基于阿里云 Kafka Serverless 提升业务弹性能力,节省成本超过 20%

作者&#xff1a;四牛 前言 云消息队列 Kafka 版 Serverless 系列凭借其秒级弹性扩展、按需付费、轻运维的优势&#xff0c;助力嘉银科技业务系统实现灵活扩缩容&#xff0c;在业务效率和成本优化上持续取得突破&#xff0c;保证服务的敏捷性和稳定性&#xff0c;并节省超过 20…

RTOS 任务状态与调度机制详解

一、任务状态概述在实时操作系统&#xff08;RTOS&#xff09;中&#xff0c;任务通常具有以下几种基本状态&#xff1a;Running&#xff08;运行态&#xff09;&#xff1a;任务正在 CPU 上实际执行。单核系统中同一时刻最多只有一个任务处于运行态。Ready&#xff08;就绪态&…

TDengine 特殊选择函数 UNIQUE 用户手册

UNIQUE 函数用户手册 函数定义 UNIQUE(expr)功能说明 UNIQUE() 函数返回指定列去重后的值&#xff0c;功能类似于 SQL 中的 DISTINCT 关键字。对于相同的数据值&#xff0c;UNIQUE 函数会返回时间戳最小的那一条记录。该函数会跳过 NULL 值。 版本要求 最低版本: v3.0.0.0…

新零售第一阶段传统零售商的困境突破与二次增长路径:基于定制开发开源AI智能名片S2B2C商城小程序的实践探索

摘要&#xff1a;新零售第一阶段&#xff0c;传统零售商面临同质化竞争、用户消费意愿低迷、线上电商分流等核心困境。本文以定制开发开源AI智能名片S2B2C商城小程序为切入点&#xff0c;结合阿里巴巴、某知名连锁零售企业等实践案例&#xff0c;分析其通过“AI智能推荐供应链协…

Spark SQL 之 Join Reorder

参考链接 https://www.cnblogs.com/fxjwind/p/14768975.html join Reorder src/main/scala/org/apache/spark/sql/catalyst/optimizer/CostBasedJoinReorder.scala private def reorder(plan: LogicalPlan, output: Seq[Attribute]): LogicalPlan = {<

牛客周赛 Round 109

比赛链接&#xff1a;牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A-小红的直角三角形_牛客周赛 Round 109 签到题&#xff1a;用勾股定理即可通过此题&#xff08;需要注意对共线情况的判断&#xff09; 代码&#xff1a; // Problem: 小红的直角三角…

[deepseek]LNK2001错误即单独编译汇编并链接

方案一&#xff1a;使用预编译的 .obj 文件&#xff08;最简单&#xff09; 如果汇编代码不常改动&#xff0c;这是最省事的方法。手动编译一次&#xff1a; 打开命令行&#xff0c;切换到 spoof.asm 所在目录。使用你已有的汇编器&#xff08;或者下载一个单独的 MASM 版本&am…

php学习 (第六天)

虚拟主机 一.什么是虚拟主机&#xff1f; 1.1 概念虚拟主机&#xff08;Web Hosting&#xff09;英文&#xff1a;Web Hosting / Shared Hosting核心概念&#xff1a; 一台服务器被切分给多个用户&#xff0c;每个人只使用服务器的一部分资源&#xff08;CPU、内存、带宽、存储…

AcousticsML声学机器学习翻译教程二(特征提取Feature Etraction)

源自&#xff1a;https://github.com/RAMshades/AcousticsM 特征提取 特征是可测量的属性&#xff0c;作为系统的输入。这些输入与特定数据样本相关&#xff0c;机器学习模型可通过解读这些特征来提供预测。特征通常具有独立性&#xff0c;并能提供样本的具体细节。音频特征示例…

【论文阅读】Beyond Text: Frozen Large Language Models in Visual Signal Comprehension

本论文研究了能否利用一个“冻结”的LLM&#xff0c;直接理解视觉信号&#xff08;即图片&#xff09;&#xff0c;而不用在多模态数据集上进行微调。核心思想是把图片看作一种“语言实体”&#xff0c;把图片转换成一组离散词汇&#xff0c;这些词汇来自LLM自己的词表。为此&a…

The Oxford-IIIT宠物图像识别数据集(753M)

0、引言博主研究生期间做的是人工智能领域相关的深度学习模型研究&#xff0c;早期还没定题的时候调研了大量方向。众所周知&#xff0c;模型性能的好坏很大程度上依赖于数据集&#xff0c;因此我当时也接触了大量数据集&#xff0c;这阵子将这些数据集汇总整理了一下&#xff…

jdbc DAO封装及BaseDAO工具类

DAO概念 DAO&#xff1a;Data Access Object&#xff0c;数据访问对象。 Java是面向对象语言&#xff0c;数据在Java中通常以对象的形式存在。一张表对应一个实体类&#xff0c;一张表的操作对应一个DAO对象&#xff01; 在Java操作数据库时&#xff0c;我们会将对同一张表的增…