应用监控详解
本章导读
没有监控的系统就像在黑暗中摸索——你永远不知道问题何时发生、发生在哪里。本章深入讲解APM工具、链路追踪、指标采集三大监控支柱,帮助读者构建全方位的系统可观测性,实现从被动救火到主动预防的转变。
学习目标:
- 目标1:理解可观测性三大支柱(Metrics、Traces、Logs)及其关联分析
- 目标2:掌握Prometheus + Micrometer实现Java应用指标采集与暴露
- 目标3:熟练运用Spring Cloud Sleuth + Zipkin进行分布式链路追踪
- 目标4:能够设计和配置Grafana Dashboard实现监控数据可视化展示
- 目标5:建立基于指标的多级告警体系实现故障快速响应
前置知识:熟悉Spring Boot应用开发,了解时序数据库概念,具备基本的运维知识
阅读时长:约 45 分钟
一、知识概述
应用监控是确保系统稳定运行的关键环节,通过实时收集、分析和展示应用的运行状态,帮助运维人员及时发现和解决问题。现代应用监控主要包括APM(应用性能监控)、链路追踪和指标采集三个方面。
1.1 监控体系架构
┌─────────────────────────────────────────────────────────────┐ │ 监控体系架构 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 数据采集层 │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ Metrics │ │ Traces │ │ Logs │ │ Events │ │ │ │ 指标 │ │ 链路 │ │ 日志 │ │ 事件 │ │ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 数据处理与存储 │ │ │ │ Prometheus / Jaeger / ELK / Kafka │ │ │ └─────────────────────┬───────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 数据分析与告警 │ │ │ │ AlertManager / Grafana / Kibana │ │ │ └─────────────────────┬───────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 可视化展示 │ │ │ │ Grafana Dashboards / Kibana / Jaeger UI │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘1.2 监控指标类型
┌─────────────────────────────────────────────────────────────┐ │ 监控指标类型 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 1. 基础设施指标 (Infrastructure Metrics) │ │ - CPU使用率、内存使用率 │ │ - 磁盘I/O、网络流量 │ │ - 系统负载、进程数 │ │ │ │ 2. 应用指标 (Application Metrics) │ │ - 请求量(QPS)、响应时间 │ │ - 错误率、成功率 │ │ - 并发连接数、线程池状态 │ │ │ │ 3. JVM指标 (JVM Metrics) │ │ - 堆内存使用、GC次数和时间 │ │ - 线程数、类加载数 │ │ - CPU使用、编译时间 │ │ │ │ 4. 业务指标 (Business Metrics) │ │ - 订单量、交易金额 │ │ - 用户活跃数、转化率 │ │ - 业务成功率、失败原因 │ │ │ │ 5. 自定义指标 (Custom Metrics) │ │ - 业务特定指标 │ │ - 缓存命中率 │ │ - 队列积压量 │ │ │ └─────────────────────────────────────────────────────────────┘1.3 三大支柱
┌─────────────────────────────────────────────────────────────┐ │ 可观测性三大支柱 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Metrics │ │ Traces │ │ Logs │ │ │ │ 指标 │ │ 链路 │ │ 日志 │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ 回答:发生了什么? 回答:哪里出了问题? 回答:为什么? │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 关联分析 │ │ │ │ 指标发现问题 → 链路定位位置 → 日志分析原因 │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘二、APM工具实践
2.1 Prometheus + Micrometer集成
<!-- pom.xml - 依赖配置 --><dependencies><!-- Spring Boot Actuator --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- Micrometer Prometheus --><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId></dependency><!-- Micrometer Core --><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-core</artifactId></dependency></dependencies># application.yml - Actuator配置management:endpoints:web:exposure:include:health,info,prometheus,metrics,heapdump,threaddumpbase-path:/actuatorendpoint:health:show-details:alwaysprometheus:enabled:truemetrics:tags:application:${spring.application.name}environment:${spring.profiles.active}distribution:percentiles-histogram:http.server.requests:truepercentiles:http.server.requests:0.5,0.9,0.95,0.99export:prometheus:enabled:true// ============================================// 自定义指标配置// ============================================@ConfigurationpublicclassMetricsConfig{@BeanpublicMeterRegistryCustomizer<MeterRegistry>metricsCommonTags(){returnregistry->registry.config().commonTags("application","myapp").commonTags("host",getHostName());}privateStringgetHostName(){try{returnInetAddress.getLocalHost().getHostName();}catch(Exceptione){return"unknown";}}}// ============================================// 业务指标收集// ============================================@ServicepublicclassOrderService{privatefinalCounterorderCounter;privatefinalCounterorderSuccessCounter;privatefinalCounterorderFailureCounter;privatefinalTimerorderProcessingTimer;privatefinalGaugependingOrdersGauge;// 自定义业务指标privatefinalAtomicLongpendingOrders=newAtomicLong(0);publicOrderService(MeterRegistrymeterRegistry){// 订单总数计数器this.orderCounter=Counter.builder("orders.total").description("总订单数").tag("type","all").register(meterRegistry);// 成功订单计数器this.orderSuccessCounter=Counter.builder("orders.success").description("成功订单数").register(meterRegistry);// 失败订单计数器this.orderFailureCounter=Counter.builder("orders.failure").description("失败订单数").tag("reason","unknown").register(meterRegistry);// 订单处理时间this.orderProcessingTimer=Timer.builder("orders.processing.time").description("订单处理时间").publishPercentiles(0.5,0.95,0.99).publishPercentileHistogram().minimumExpectedValue(Duration.ofMillis(100)).maximumExpectedValue(Duration.ofSeconds(10)).register(meterRegistry);// 待处理订单数量this.pendingOrdersGauge=Gauge.builder("orders.pending",pendingOrders,AtomicLong::get).description("待处理订单数量").register(meterRegistry);}publicOrdercreateOrder(OrderRequestrequest){returnorderProcessingTimer.record(()->{orderCounter.increment();pendingOrders.incrementAndGet();try{// 处理订单逻辑Orderorder=processOrder(request);orderSuccessCounter.increment();returnorder;}catch(Exceptione){orderFailureCounter.increment();throwe;}finally{pendingOrders.decrementAndGet();}});}privateOrderprocessOrder(OrderRequestrequest){// 订单处理逻辑returnnewOrder();}}// ============================================// HTTP请求指标收集// ============================================@ComponentpublicclassHttpMetricsFilterimplementsWebMvcTagsProvider{@OverridepublicIterable<Tag>getTags(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Throwableexception){returnArrays.asList(Tag.of("method",request.getMethod()),Tag.of("uri",getUriTemplate(request)),Tag.of("status",String.valueOf(response.getStatus())),Tag.of("exception",exception!=null?exception.getClass().getSimpleName():"none"));}privateStringgetUriTemplate(HttpServletRequestrequest){Stringuri=request.getRequestURI();// 参数化URI,避免高基数问题returnuri.replaceAll("/\\d+","/{id}");}}// ============================================// 缓存指标监控// ============================================@ServicepublicclassCacheService{privatefinalCountercacheHitCounter;privatefinalCountercacheMissCounter;privatefinalTimercacheGetTimer;public