应用上线只是第一步,持续掌握应用的运行状态、快速定位问题、在故障发生前及时响应,才是生产环境运维的核心能力。本节构建一套面向 Spring Boot 应用的轻量级、可落地的监控体系,覆盖指标采集、日志收集与告警通知三大模块,确保即使小团队也能做到可观测性不缺失。
20.4.1 指标采集:用 Micrometer 统一暴露应用指标
Spring Boot 默认集成了 Micrometer,它是一套指标门面,能以统一的 API 将 JVM、框架和自定义指标导出到不同的监控后端(Prometheus、InfluxDB、Elasticsearch 等)。常用的采集粒度包括:
- JVM 指标:内存使用、GC 次数与耗时、线程数、类加载数。
- HTTP 请求指标:请求次数、响应时间分布、错误率(通过
spring-boot-starter-actuator+ 合适的 Web 容器指标)。 - 数据源指标:HikariCP 连接池的活跃连接数、等待线程数、连接超时次数。
- 业务自定义指标:订单创建速率、支付成功率、某缓存命中率等。
接入方案:Actuator + Micrometer + Prometheus
- 添加依赖(以 Gradle 为例,Maven 同理):
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'
- 暴露端点,在
application.yml中开放 Prometheus 格式的指标端点:
management:
endpoints:
web:
exposure:
include: health,info,prometheus
metrics:
tags:
application: ${spring.application.name}
此时访问 /actuator/prometheus 即可看到大量指标数据。
- 部署 Prometheus(生产建议使用 Operator 或托管服务),在
prometheus.yml中添加抓取任务:
scrape_configs:
- job_name: 'spring-boot'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['app-host:8080']
- 自定义业务指标示例:使用
MeterRegistry注入,定义计数器或计时器。
@RestController
public class OrderController {
private final Counter orderCreateCounter;
public OrderController(MeterRegistry registry) {
this.orderCreateCounter = Counter.builder("orders.created")
.description("Number of created orders")
.register(registry);
}
@PostMapping("/orders")
public void createOrder() {
// 业务逻辑
orderCreateCounter.increment();
}
}
通过这套机制,所有实例的指标被 Prometheus 定期拉取并存储,Grafana 以数据源形式接入 Prometheus,即可用图表直观展示。无需额外改造,Spring Boot 应用就具备了生产级指标输出能力。
20.4.2 日志收集:从 Console 到集中存储与检索
日志是排查问题的第一手资料。微服务实例化后,日志散落在各自的容器/服务器中,必须集中收集才能发挥效用。主流的方案有两种:
- ELK/EFK 栈:Elasticsearch + Logstash/Fluentd + Kibana,功能强大,适合大日志量和复杂分析场景。
- Loki 栈:Grafana Loki + Promtail,轻量,原生集成 Grafana,存储成本低,适合中小规模或成本敏感场景。
这里以 EFK(Elasticsearch + Fluentd + Kibana) 为例,展示与 Spring Boot 应用的整合方式。Fluentd 作为采集器,比 Logstash 更轻量,资源占用小,且在 Kubernetes 中部署简便。
步骤一:应用侧输出 JSON 格式日志
为使 Fluentd 高效解析,建议将 Spring Boot 日志格式设置为 JSON。在 logback-spring.xml 中配置 LogstashEncoder(需要 net.logstash.logback:logstash-logback-encoder 依赖):
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
此时日志将输出含 timestamp、level、logger、message 及 MDC 字段的 JSON 行,便于后续索引。
步骤二:Fluentd 收集并转发到 Elasticsearch
在 Kubernetes 中,通常以 DaemonSet 部署 Fluentd,挂载宿主机日志目录,解析容器标准输出。简单的 fluent.conf 配置片段:
<source>
@type tail
path /var/log/containers/*.log
pos_file /var/log/fluentd-containers.log.pos
tag kubernetes.*
<parse>
@type json
</parse>
</source>
<match kubernetes.**>
@type elasticsearch
host elasticsearch-logging
port 9200
logstash_format true
logstash_prefix spring-app
include_tag_key true
</match>
Fluentd 将 JSON 日志按天索引至 Elasticsearch,Kibana 即可进行全文检索和可视化。
步骤三:关联指标与日志
在实践中,为了通过一条 Trace ID 或请求 ID 将指标(如慢请求)和日志串起来,需要在请求入口生成唯一标识并放入 MDC,同时在响应头返回。例如使用 Spring Cloud Sleuth 自动注入 traceId 和 spanId,或在 Filter 中手动设置:
String requestId = UUID.randomUUID().toString().substring(0,8);
MDC.put("requestId", requestId);
在日志 JSON 中此字段会被自动包含,后续排查问题时,只需在 Kibana 中搜索该请求 ID 即可完整还原调用链路。
20.4.3 告警机制:从被动观测到主动响应
光有指标和日志还不够,需要基于它们定义异常规则,让系统在出现异常时自动通知到人。Prometheus + Alertmanager 是目前社区使用最广泛的组合,其告警规则灵活,通知渠道丰富。
Prometheus 告警规则示例
定义延迟和错误率规则,保存为 spring-app-rules.yml 并在 Prometheus 配置中引用:
groups:
- name: spring-application
rules:
- alert: HighRequestLatency
expr: histogram_quantile(0.99, rate(http_server_requests_seconds_bucket[5m])) > 1
for: 3m
labels:
severity: warning
annotations:
summary: "P99 latency over 1s (instance {{ $labels.instance }})"
description: "The 99th percentile latency has been higher than 1 second for 3 minutes"
- alert: ErrorRateHigh
expr: rate(http_server_requests_seconds_count{status=~"5.."}[5m]) / rate(http_server_requests_seconds_count[5m]) > 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "Error rate > 5%"
description: "Service {{ $labels.application }} has a 5xx error rate of {{ $value | humanizePercentage }}"
Alertmanager 配置通知
Alertmanager 负责接收 Prometheus 推送的告警,去重、分组后路由到邮件、钉钉/飞书/企业微信或 PagerDuty 等。例如配置钉钉群机器人通知(需部署 prometheus-webhook-dingtalk 中间件或使用 Alertmanager 的 webhook 直接调用):
route:
receiver: 'dingtalk'
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receivers:
- name: 'dingtalk'
webhook_configs:
- url: 'http://dingtalk-webhook:8060/dingtalk/webhook1/send'
send_resolved: true
当告警被触发,相关人员会立刻在 IM 工具中收到消息,包含告警摘要、实例信息等。配合 Grafana 仪表板链接,可一键跳转到出问题时段的可视化视图。
告警的实用原则
- 避免告警风暴:设置合理的
for持续时间,防止瞬时抖动触发大量告警。 - 按严重程度分级:warning 级别仅作提醒,critical 则需要立即介入。
- 告警必须可操作:每一条告警都应能指向具体的排查动作,否则就是噪音。
- 持续优化:定期回顾告警历史,去除无效告警,调整阈值,使监控真正成为团队的“安全网”。
20.4.4 最小化落地清单
对于资源有限的小团队,不必一次性搭建重型平台,可遵循以下顺序渐进增强:
- 所有项目引入 Actuator + Micrometer + Prometheus 依赖,指标端口对外暴露。
- 部署单节点 Prometheus + Grafana(Docker 一键启动),导入 Spring Boot 通用仪表板(社区 ID:10254、12900 等),即可看到内存、HTTP 请求等核心指标。
- 日志 JSON 化,并输出到 stdout;测试环境使用
docker-compose启一个 ELK 或 Loki 栈,验证日志集中查询可行性。 - 关键接口定义 Prometheus 告警规则,配置 Alertmanager 发送到企业微信群机器人,确保有人接收到。
当这套基础监控成型后,再逐步引入分布式链路追踪(如 SkyWalking 或 Zipkin)、更复杂的分位数告警、基于日志的异常检测等,形成纵深防御式的可观测体系。
线上环境不可控,但监控可以预测。有了上述组合拳,应用的任何健康波动都将变成可感知、可追查、可行动的信号,而不是生产事故后的追悔莫及。