Appearance
Spring Boot Observability:现代应用监控的三大支柱 🔍
什么是 Observability?为什么它如此重要?
想象一下,你正在运营一个在线购物网站。突然,用户开始抱怨页面加载缓慢,订单提交失败。作为开发者,你需要快速定位问题:
- 是数据库查询太慢?
- 是某个微服务出现了故障?
- 还是网络连接有问题?
这就是 Observability(可观测性) 要解决的核心问题:让我们能够从外部观察运行中系统的内部状态。
IMPORTANT
Observability 由三大支柱构成:
- Logging(日志):记录系统发生了什么
- Metrics(指标):量化系统的性能表现
- Traces(链路追踪):追踪请求在系统中的完整流程
Spring Boot 中的 Observability 架构
Spring Boot 使用 Micrometer Observation 来统一处理指标和链路追踪,这是一个革命性的设计理念:
TIP
一次观测,多重收益!通过 Micrometer Observation,你只需要编写一次观测代码,就能同时获得指标和链路追踪数据。
创建自定义观测:从零到一的实践
让我们通过一个实际的电商订单处理场景来学习如何使用 Observability:
kotlin
@Service
class OrderService {
fun processOrder(orderId: String): Order {
// 记录日志
logger.info("开始处理订单: $orderId")
// 记录指标
orderCounter.increment()
val timer = Timer.start()
try {
// 业务逻辑
val order = validateOrder(orderId)
val payment = processPayment(order)
val shipment = createShipment(order)
logger.info("订单处理成功: $orderId")
return order
} catch (e: Exception) {
logger.error("订单处理失败: $orderId", e)
errorCounter.increment()
throw e
} finally {
timer.stop(orderProcessingTimer)
}
}
}
kotlin
@Service
class OrderService(
private val observationRegistry: ObservationRegistry
) {
fun processOrder(orderId: String): Order {
return Observation.createNotStarted("order.process", observationRegistry)
.lowCardinalityKeyValue("order.type", "standard") // 用于指标和链路追踪
.highCardinalityKeyValue("order.id", orderId) // 仅用于链路追踪
.observe {
// 业务逻辑 - 清晰分离
val order = validateOrder(orderId)
val payment = processPayment(order)
val shipment = createShipment(order)
order
}
}
}
NOTE
Low Cardinality vs High Cardinality 标签的区别:
- Low Cardinality:值的种类有限(如订单类型:standard、premium、vip),会同时添加到指标和链路追踪中
- High Cardinality:值的种类很多(如用户ID、订单ID),仅添加到链路追踪中,避免指标维度爆炸
上下文传播:跨线程和响应式流的观测
在现代应用中,一个请求可能会跨越多个线程和响应式流。Spring Boot 提供了强大的上下文传播机制:
kotlin
@Configuration
class ObservabilityConfig {
@Bean
fun reactorContextPropagation(): ReactorContextPropagation {
// 启用响应式流中的上下文传播
return ReactorContextPropagation()
}
}
@Service
class AsyncOrderService(
private val observationRegistry: ObservationRegistry
) {
@Async
fun processOrderAsync(orderId: String): CompletableFuture<Order> {
// 观测上下文会自动传播到异步线程中
return Observation.createNotStarted("order.async.process", observationRegistry)
.observe {
// 异步业务逻辑
processComplexOrder(orderId)
}
}
fun processOrderReactive(orderId: String): Mono<Order> {
return Observation.createNotStarted("order.reactive.process", observationRegistry)
.observe {
// 响应式业务逻辑
Mono.fromCallable { processComplexOrder(orderId) }
.subscribeOn(Schedulers.boundedElastic())
}
}
}
启用自动上下文传播
在 application.yml
中设置:
yaml
spring:
reactor:
context-propagation: auto # 启用响应式流中的自动上下文传播
通用标签:为所有观测添加环境信息
通用标签让你能够按照环境维度对所有观测数据进行分析:
properties
# 为所有观测添加通用标签
management.observations.key-values.region=us-east-1
management.observations.key-values.stack=prod
management.observations.key-values.service=order-service
management.observations.key-values.version=1.2.3
yaml
management:
observations:
key-values:
region: "us-east-1" # 部署区域
stack: "prod" # 环境标识
service: "order-service" # 服务名称
version: "1.2.3" # 服务版本
这样配置后,所有的观测数据都会自动包含这些标签,便于在监控系统中进行多维度分析。
观测控制:精确管理你想要的数据
1. 通过配置禁用特定观测
有时候某些观测可能产生过多噪音,你可以选择性地禁用它们:
properties
# 禁用特定前缀的观测
management.observations.enable.http.client=false
management.observations.enable.spring.security=false
management.observations.enable.jdbc=false
yaml
management:
observations:
enable:
http:
client: false # 禁用 HTTP 客户端观测
spring:
security: false # 禁用 Spring Security 观测
jdbc: false # 禁用 JDBC 观测
2. 通过代码实现精细控制
对于更复杂的控制逻辑,你可以实现 ObservationPredicate
:
kotlin
@Component
class CustomObservationPredicate : ObservationPredicate {
override fun test(name: String, context: Observation.Context): Boolean {
// 禁用健康检查相关的观测
if (name.contains("health")) {
return false
}
// 只在生产环境启用详细的数据库观测
if (name.startsWith("jdbc") && !isProductionEnvironment()) {
return false
}
// 根据请求路径过滤
if (context is ServerRequestObservationContext) {
val uri = context.carrier?.requestURI
return !uri?.startsWith("/internal/")
}
return true
}
private fun isProductionEnvironment(): Boolean {
// 检查环境逻辑
return System.getProperty("spring.profiles.active")?.contains("prod") == true
}
}
WARNING
观测控制要谨慎使用!过度禁用观测可能会让你在关键时刻失去重要的监控数据。
注解驱动的观测:让监控更简单
Spring Boot 支持通过注解来启用观测,让代码更加简洁:
kotlin
# 启用注解支持
management:
observations:
annotations:
enabled: true
kotlin
@Service
class ProductService {
@Observed(
name = "product.search",
contextualName = "product-search-by-category",
lowCardinalityKeyValues = ["operation", "search"]
)
fun searchProducts(
@MeterTag("category") category: String, // 自动添加为标签
@MeterTag("limit") limit: Int
): List<Product> {
// 业务逻辑 - 自动被观测
return productRepository.findByCategory(category, limit)
}
@Timed(name = "product.creation.time", description = "产品创建耗时")
@Counted(name = "product.creation.count", description = "产品创建次数")
fun createProduct(product: Product): Product {
// 同时记录耗时和计数
return productRepository.save(product)
}
}
CAUTION
避免重复观测!如果你的方法已经被 Spring 自动观测(如 Spring MVC 控制器、Spring Data 仓库),再添加注解会产生重复的观测数据。
OpenTelemetry 集成:标准化的可观测性
Spring Boot 提供了对 OpenTelemetry 的原生支持:
kotlin
@Configuration
class OpenTelemetryConfig {
@Bean
fun openTelemetryResource(): Resource {
return Resource.getDefault()
.merge(Resource.builder()
.put(ResourceAttributes.SERVICE_NAME, "order-service")
.put(ResourceAttributes.SERVICE_VERSION, "1.0.0")
.put(ResourceAttributes.DEPLOYMENT_ENVIRONMENT, "production")
.build())
}
@Bean
fun sdkTracerProvider(): SdkTracerProvider {
return SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(
OtlpGrpcSpanExporter.builder()
.setEndpoint("http://jaeger:14250")
.build()
).build())
.setResource(openTelemetryResource())
.build()
}
}
OpenTelemetry 配置示例
yaml
management:
opentelemetry:
resource-attributes:
service.name: "order-service"
service.version: "1.0.0"
deployment.environment: "production"
team: "backend"
实战场景:电商系统的完整观测方案
让我们通过一个完整的电商订单处理流程来展示 Observability 的威力:
kotlin
@RestController
@RequestMapping("/api/orders")
class OrderController(
private val orderService: OrderService,
private val observationRegistry: ObservationRegistry
) {
@PostMapping
fun createOrder(@RequestBody orderRequest: OrderRequest): ResponseEntity<Order> {
return Observation.createNotStarted("order.api.create", observationRegistry)
.lowCardinalityKeyValue("order.type", orderRequest.type)
.lowCardinalityKeyValue("payment.method", orderRequest.paymentMethod)
.highCardinalityKeyValue("user.id", orderRequest.userId.toString())
.observe {
val order = orderService.processOrder(orderRequest)
ResponseEntity.ok(order)
}
}
}
@Service
class OrderService(
private val paymentService: PaymentService,
private val inventoryService: InventoryService,
private val observationRegistry: ObservationRegistry
) {
fun processOrder(orderRequest: OrderRequest): Order {
return Observation.createNotStarted("order.service.process", observationRegistry)
.observe {
// 1. 验证库存
val inventoryCheck = Observation.createNotStarted("inventory.check", observationRegistry)
.observe { inventoryService.checkAvailability(orderRequest.items) }
if (!inventoryCheck.available) {
throw InsufficientInventoryException("库存不足")
}
// 2. 处理支付
val payment = Observation.createNotStarted("payment.process", observationRegistry)
.lowCardinalityKeyValue("payment.method", orderRequest.paymentMethod)
.observe { paymentService.processPayment(orderRequest.payment) }
// 3. 创建订单
val order = Order(
id = generateOrderId(),
items = orderRequest.items,
payment = payment,
status = OrderStatus.CONFIRMED
)
// 4. 扣减库存
Observation.createNotStarted("inventory.reserve", observationRegistry)
.observe { inventoryService.reserveItems(orderRequest.items) }
order
}
}
}
通过这种方式,你可以在监控系统中看到:
- 📊 指标数据:订单创建成功率、平均处理时间、不同支付方式的分布
- 🔍 链路追踪:完整的请求流程,包括每个步骤的耗时和依赖关系
- 📝 结构化日志:与观测上下文关联的日志信息
最佳实践总结
观测命名规范
- 使用点号分隔的层次结构:
service.operation.action
- 保持名称简洁且有意义:
order.payment.process
而不是processOrderPayment
- 使用一致的命名约定
标签使用策略
- Low Cardinality:环境、服务类型、操作类型等固定值
- High Cardinality:用户ID、订单ID、会话ID等唯一值
- 避免在标签中使用时间戳或随机值
性能考虑
- 观测本身也有性能开销,在高并发场景下要合理控制观测的粒度
- 使用采样策略减少链路追踪的数据量
- 定期清理不再需要的观测点
总结
Spring Boot 的 Observability 为我们提供了一套完整、现代化的应用监控解决方案。通过统一的 API,我们可以:
✅ 简化监控代码:一次编写,多重收益
✅ 提升可维护性:清晰分离业务逻辑和监控逻辑
✅ 增强问题定位能力:完整的链路追踪和丰富的指标数据
✅ 支持现代架构:异步、响应式、微服务友好
在微服务和云原生时代,Observability 不再是可选项,而是必需品。掌握 Spring Boot 的 Observability 特性,让你的应用在复杂的生产环境中始终保持透明和可控! 🚀