SpringBoot 4.0新特性解析:Resilience之失败重试
从Spring 7.0版本开始,Spring Framework核心模块集成了常用的Resilience(弹性)相关功能,主要包括对方法调用的失败重试 支持以及并发控制支持。作为默认依赖Spring 7.0的SpringBoot 4.0,自然也就具备了这些强大的弹性能力。
本文将重点介绍SpringBoot 4.0中的失败重试特性,下一篇将深入探讨并发控制。
一、注解式失败重试:@Retryable
@Retryable 注解提供了一种声明式的方式来实现方法的重试逻辑。它可以标注在单个方法上,为该方法设置特定的重试策略;也可以标注在类上,为类中所有通过代理调用的方法统一指定重试特性。
1. 快速上手:两步开启重试
第一步:在启动类启用弹性方法支持
使用 @EnableResilientMethods 注解开启Spring的弹性方法处理能力。
java
@EnableResilientMethods
@SpringBootApplication
public class Springboot4Application {
public static void main(String[] args) {
SpringApplication.run(Springboot4Application.class, args);
}
}
第二步:在业务方法上添加 @Retryable
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.retry.annotation.Retryable;
@RestController
public class RetryController {
private static final Logger log = LoggerFactory.getLogger(RetryController.class);
@Retryable
@GetMapping(path = "/demo")
public String demo() {
log.info("RetryController demo 被调用");
// 模拟一个运行时异常,触发重试
int a = 1 / 0;
return "demo";
}
}
默认重试行为:
- 触发条件:方法抛出任何类型的异常。
- 重试次数 :初始调用失败后,最多进行 3 次 重试尝试(
maxRetries = 3)。因此,如果业务方法持续失败,总计会被调用 1(初始)+ 3(重试)= 4 次。 - 重试间隔 :每次重试之间默认间隔 1 秒(delay = 1000ms)。
2. 自定义重试策略
@Retryable 提供了丰富的属性,允许开发者精细控制重试行为。
| 属性 | 类型 | 描述 | 默认值 |
|---|---|---|---|
maxRetries |
int |
最大重试次数(不包含初始调用)。 | 3 |
delay |
long |
初次调用失败后,到第一次重试之间的基础延迟时长(毫秒)。 | 1000 (1秒) |
maxDelay |
long |
任何一次重试尝试的最大延迟时长(毫秒)。用于限制因 multiplier 或 jitter 导致的延迟过度增长。 |
0 (不限制) |
multiplier |
double |
用于计算下一次重试延迟的倍数。下一次延迟 = 上一次延迟 * multiplier。 |
1.0 (固定间隔) |
jitter |
long |
为每次重试延迟添加的随机抖动值(毫秒)。实际延迟会在 [计算延迟 - jitter, 计算延迟 + jitter] 范围内浮动,但不会低于 delay 或高于 maxDelay。 |
0 (无抖动) |
示例:复杂重试策略
java
@Retryable(
maxRetries = 3,
delay = 1000,
maxDelay = 5000,
multiplier = 3,
jitter = 100
)
@GetMapping(path = "/demo")
public String demo() { // ... }
运行日志分析:
2026-01-22T15:37:13 INFO -- [8080-exec-1] RetryController : RetryController demo // 初始调用
2026-01-22T15:37:14 INFO -- [8080-exec-1] RetryController : RetryController demo // 第1次重试,延迟1秒
2026-01-22T15:37:17 INFO -- [8080-exec-1] RetryController : RetryController demo // 第2次重试,延迟 1秒 * 3 = 3秒
2026-01-22T15:37:22 INFO -- [8080-exec-1] RetryController : RetryController demo // 第3次重试,延迟 3秒 * 3 = 9秒,但因maxDelay=5秒,实际延迟5秒
2026-01-22T15:37:22 ERROR -- [8080-exec-1] [dispatcherServlet]: Servlet.service() for... // 重试次数耗尽,最终抛出异常
注意:在整个重试过程中,原始请求线程会一直阻塞,直到重试耗尽并抛出最终异常。这意味着接口的响应时间可能会显著增加(如上例,总耗时超过8秒)。
3. 自定义触发重试的异常类型
默认情况下,所有异常都会触发重试。您可以通过以下属性精确控制哪些异常应该或不应该触发重试。
| 属性 | 类型 | 描述 | 优先级 |
|---|---|---|---|
includes |
Class<? extends Throwable>[] |
指定应触发重试的异常类型。 | 中 |
excludes |
Class<? extends Throwable>[] |
指定不应触发重试的异常类型。 | 高 |
predicate |
Class<? extends MethodRetryPredicate> |
通过自定义MethodRetryPredicate实现类进行更复杂的条件判断。 |
低 |
示例:排除特定异常
java
@Retryable(
includes = RuntimeException.class, // 包含所有RuntimeException及其子类
excludes = ArithmeticException.class // 但排除ArithmeticException
)
@GetMapping(path = "/demo")
public String demo() {
log.info("RetryController demo");
int a = 1/0; // 抛出ArithmeticException,被excludes命中,**不会触发重试**
return "demo";
}
二、编程式失败重试:RetryTemplate
与声明式的 @Retryable 不同,RetryTemplate 提供了一套API,允许您以编程的方式对任意代码块进行重试控制。使用 RetryTemplate 时,无需 在启动类上添加 @EnableResilientMethods 注解。
1. 基础用法
java
import org.springframework.retry.support.RetryTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RetryController {
@GetMapping(path = "/demo2")
public String demo2() throws Exception {
// 1. 创建RetryTemplate实例
RetryTemplate retryTemplate = new RetryTemplate();
// 2. 使用execute方法执行需要重试的逻辑
return retryTemplate.execute(context -> {
log.info("RetryController demo2 被调用");
int a = 1 / 0; // 模拟异常
return "demo2";
});
}
}
RetryTemplate 默认的重试策略与 @Retryable 一致:重试所有异常,最多重试3次,每次间隔1秒。
2. 自定义重试策略
您可以通过构建 RetryPolicy 对象来精细控制 RetryTemplate 的行为。
java
import org.springframework.retry.RetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import java.time.Duration;
@GetMapping(path = "/demo2")
public String demo2() throws Exception {
// 1. 构建自定义的RetryPolicy
RetryPolicy retryPolicy = RetryPolicy.builder()
.maxRetries(3) // 最大重试次数
.delay(Duration.ofMillis(1000)) // 基础延迟
.maxDelay(Duration.ofMillis(5000)) // 最大延迟
.multiplier(3) // 延迟倍数
.jitter(Duration.ofMillis(100)) // 抖动时间
.includes(RuntimeException.class) // 包含的异常
.excludes(ArithmeticException.class) // 排除的异常
.build();
// 2. 将策略注入到RetryTemplate
RetryTemplate retryTemplate = new RetryTemplate(retryPolicy);
// 3. 执行需要重试的代码
return retryTemplate.execute(context -> {
log.info("RetryController demo2 被调用");
int a = 1 / 0; // 模拟ArithmeticException,根据策略,此异常被排除,不会重试
return "demo2";
});
}
SpringBoot 4.0 内置的失败重试功能为构建健壮的微服务应用提供了强大而便捷的支持:
@Retryable注解:适用于大多数场景,通过声明式配置,快速、简洁地为特定方法或类添加重试能力。RetryTemplate编程式API:提供了更高的灵活性,允许在代码块级别动态控制重试逻辑,适用于更复杂的业务场景。
两种方式都支持精细化的策略配置,包括重试次数、动态延迟、异常过滤等,能够有效应对网络抖动、临时性服务不可用等问题,提升应用的容错性和用户体验。
SpringBoot 4.0新特性解析:Resilience之并发限制
继上一篇文章介绍了失败重试特性后,今天我们来学习SpringBoot 4.0中另一个重要的弹性能力------并发限制 。通过@ConcurrencyLimit注解,我们可以轻松控制方法的并发访问数量,实现简易但高效的限流功能。
一、注解式并发限制:@ConcurrencyLimit
@ConcurrencyLimit注解与@Retryable类似,既可以标注在单个方法上,为特定方法设置并发限制,也可以标注在类上,为类中所有通过代理调用的方法统一设置并发限制。
1. 快速上手:两步开启并发限制
第一步:在启动类启用弹性方法支持
与重试特性共享同一个开关注解:
java
@EnableResilientMethods
@SpringBootApplication
public class Springboot4Application {
public static void main(String[] args) {
SpringApplication.run(Springboot4Application.class, args);
}
}
第二步:在业务方法上添加@ConcurrencyLimit
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.resilience.concurrency.annotation.ConcurrencyLimit;
@RestController
@RequestMapping("/api/concurrency-limit")
public class ConcurrencyLimitController {
private static final Logger log = LoggerFactory.getLogger(ConcurrencyLimitController.class);
@ConcurrencyLimit(limit = 1)
@GetMapping(path = "/demo")
public String demo() throws InterruptedException {
log.info("ConcurrencyLimitController demo 被调用");
// 模拟业务处理耗时
Thread.sleep(1000);
return "demo - " + LocalDateTime.now();
}
}
limit = 1 :表示该方法同时只允许1个并发访问。当超过限制的并发请求到来时,请求线程会阻塞等待,直到前面的请求处理完毕释放许可。
2. 效果测试
下面通过一个并发测试来验证限流效果:
java
public static void main(String[] args) throws Exception {
System.out.println("start at " + LocalDateTime.now());
int threadCount = 5;
CountDownLatch start = new CountDownLatch(1);
CountDownLatch stop = new CountDownLatch(threadCount);
// 创建5个并发线程
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
try {
start.await(); // 等待统一启动信号
String res = new RestTemplate()
.getForObject("http://localhost:8080/api/concurrency-limit/demo",
String.class);
System.out.println(res);
stop.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
// 统一启动所有线程
start.countDown();
stop.await(); // 等待所有线程完成
System.out.println("end at " + LocalDateTime.now());
}
运行结果分析:
start at 2026-01-23T12:52:42.123
// 服务端日志 - 每秒处理一个请求
2026-01-23T12:52:43 INFO -- [nio-exec-4] ConcurrencyLimitController : demo 被调用 // 第1个请求
2026-01-23T12:52:44 INFO -- [nio-exec-2] ConcurrencyLimitController : demo 被调用 // 第2个请求
2026-01-23T12:52:45 INFO -- [nio-exec-5] ConcurrencyLimitController : demo 被调用 // 第3个请求
2026-01-23T12:52:46 INFO -- [nio-exec-3] ConcurrencyLimitController : demo 被调用 // 第4个请求
2026-01-23T12:52:47 INFO -- [nio-exec-1] ConcurrencyLimitController : demo 被调用 // 第5个请求
// 客户端响应时间
demo - 2026-01-23T12:52:43
demo - 2026-01-23T12:52:44
demo - 2026-01-23T12:52:45
demo - 2026-01-23T12:52:46
demo - 2026-01-23T12:52:47
end at 2026-01-23T12:52:47.456
由于接口只允许1个并发,5个请求被串行处理,每个请求耗时1秒,总执行时长超过5秒。这验证了并发限制功能确实生效了。
3. 注解属性详解
@ConcurrencyLimit注解主要包含以下属性:
| 属性 | 类型 | 描述 | 默认值 |
|---|---|---|---|
limit |
int |
最大并发访问数 | Integer.MAX_VALUE (不限制) |
timeout |
int |
获取许可的超时时间(毫秒) | -1 (无限等待) |
queueCapacity |
int |
等待队列容量 | Integer.MAX_VALUE |
超时配置示例:
java
@ConcurrencyLimit(limit = 1, timeout = 100)
@GetMapping(path = "/demo-with-timeout")
public String demoWithTimeout() throws InterruptedException {
log.info("demoWithTimeout 被调用");
Thread.sleep(200); // 模拟处理耗时
return "demo-with-timeout";
}
当并发超过限制时,等待线程最多等待100毫秒,如果超时仍无法获取许可,将抛出ConcurrencyThrottleTimeoutException异常。
二、实现原理与编程式控制
@ConcurrencyLimit的背后是ConcurrencyThrottleSupport类,它是Spring框架提供的并发控制支持类。除了使用注解,我们也可以通过编程方式手动实现并发控制。
1. 使用SyncTaskExecutor实现并发限制
SyncTaskExecutor内部使用了ConcurrencyThrottleSupport来实现并发控制:
java
import org.springframework.core.task.SyncTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ConcurrencyLimitController {
// 创建配置了并发限制的SyncTaskExecutor
private SyncTaskExecutor taskExecutor = new SyncTaskExecutor() {{
// 设置最大并发数为1
this.setConcurrencyLimit(1);
}};
@GetMapping(path = "/demo2")
public String demo2() throws Exception {
// 通过execute方法执行任务,自动受并发限制控制
return taskExecutor.execute(() -> {
log.info("ConcurrencyLimitController demo2 被调用");
Thread.sleep(1000); // 模拟业务处理
return "demo2 - " + LocalDateTime.now();
});
}
}
2. 直接使用ConcurrencyThrottleSupport
如果需要更精细的控制,可以直接使用ConcurrencyThrottleSupport:
java
import org.springframework.util.ConcurrencyThrottleSupport;
@RestController
public class ConcurrencyLimitController {
private final ConcurrencyThrottleSupport throttle = new ConcurrencyThrottleSupport();
public ConcurrencyLimitController() {
throttle.setConcurrencyLimit(1); // 设置并发限制
}
@GetMapping(path = "/demo3")
public String demo3() throws Exception {
try {
// 尝试获取许可
throttle.beforeAccess();
// 业务逻辑
log.info("ConcurrencyLimitController demo3 被调用");
Thread.sleep(1000);
return "demo3 - " + LocalDateTime.now();
} finally {
// 释放许可
throttle.afterAccess();
}
}
}
3. 与@Async结合使用
并发限制可以与@Async异步执行结合,实现更复杂的场景:
java
@RestController
public class ConcurrencyLimitController {
@Async // 异步执行
@ConcurrencyLimit(limit = 2) // 控制异步任务的并发数
@GetMapping(path = "/demo4")
public CompletableFuture<String> demo4() {
log.info("demo4 被调用,当前线程:{}", Thread.currentThread().getName());
return CompletableFuture.completedFuture("demo4");
}
}
三、应用场景与最佳实践
1. 典型应用场景
- API限流:保护后端服务不被突发流量打垮
- 数据库连接控制:限制对数据库的高并发访问
- 第三方API调用:防止超出第三方服务的配额限制
- 资源密集型操作:控制CPU/内存密集型操作的并发数
2. 注意事项
-
阻塞 vs 拒绝 :
@ConcurrencyLimit默认采用阻塞策略,超出限制的请求会等待而非直接拒绝。如需快速失败,可通过timeout参数设置超时时间。 -
线程池关系 :并发限制是在应用层面的控制,与底层的线程池无关。即使线程池有10个线程,
limit=1也能确保同时只有一个请求执行业务逻辑。 -
事务边界 :如果同时使用
@Transactional和@ConcurrencyLimit,需要注意注解的执行顺序。建议将@ConcurrencyLimit放在外层。
3. 与Resilience4j对比
| 特性 | Spring 7.0内置 | Resilience4j |
|---|---|---|
| 并发限制 | ✅ @ConcurrencyLimit |
✅ Bulkhead |
| 实现方式 | 注解+编程式 | 注解+编程式 |
| 等待策略 | 阻塞等待 | 可配置(阻塞/快速失败) |
| 集成度 | 与Spring生态无缝集成 | 需额外依赖 |
SpringBoot 4.0通过@ConcurrencyLimit注解为开发者提供了一种简洁高效的并发控制方案:
- 声明式配置:通过简单的注解即可实现方法级别的并发限制
- 灵活的策略:支持并发数、超时时间等参数的自定义
- 编程式支持 :提供了
ConcurrencyThrottleSupport和SyncTaskExecutor等API - 零侵入集成:与Spring生态完美融合,学习成本低
通过合理使用并发限制特性,我们可以有效提升应用的稳定性和资源利用率,构建更加健壮的微服务系统。
扩展阅读:
注:本文基于Spring 7.0/SpringBoot 4.0预览版特性编写,最终发布版本可能略有调整。
SpringBoot 4.0新特性解析:Observability让生产环境更易于观测
系统的可观测性(Observability)是指从系统外部观察运行中系统内部状态的能力,它由三大支柱构成:日志记录(Logs) 、指标收集(Metrics)和链路追踪(Traces) 。SpringBoot 4.0提供了全新的spring-boot-starter-opentelemetry来提供可观测性支持,无需借助传统的Actuator。其核心优势在于原生支持OTLP协议,虽然内部使用Micrometer,但所有数据都通过OTLP协议导出至任何兼容的后端系统。
一、架构概览
本文演示如何快速搭建一套完整的可观测性系统并接入SpringBoot应用,整体架构如下:
SpringBoot应用
OTLP协议
OpenTelemetry Collector
Prometheus
指标存储
Tempo
链路存储
Loki
日志存储
Grafana
统一UI展示
数据流转说明:
- SpringBoot应用通过OTLP协议将指标、链路、日志数据发送给OpenTelemetry Collector
- Collector将指标转发给Prometheus
- Collector将链路转发给Tempo
- Collector将日志转发给Loki
- Grafana从各个数据源读取数据,提供统一的UI展示
二、快速搭建LGTM系统
使用docker-compose可以快速构建一套完整的LGTM(Loki + Grafana + Tempo + Metrics)系统。
2.1 docker-compose配置
创建compose.yaml文件:
yaml
services:
grafana-lgtm:
image: 'grafana/otel-lgtm:latest'
ports:
- '3000:3000' # Grafana UI端口
- '4317:4317' # OTLP gRPC端口
- '4318:4318' # OTLP HTTP端口
镜像说明 :grafana/otel-lgtm是一个All-in-One镜像,包含了以下组件:
- OpenTelemetry Collector:接收并转发遥测数据
- Prometheus:指标存储与查询
- Tempo:链路追踪存储
- Loki:日志存储
- Grafana:可视化UI
2.2 启动LGTM系统
bash
docker-compose up -d
启动成功后,可以通过以下地址访问各组件:
- Grafana UI:http://localhost:3000 (默认用户名/密码:admin/admin)
- OTLP gRPC端点:localhost:4317
- OTLP HTTP端点:localhost:4318
三、SpringBoot应用接入可观测性
3.1 创建SpringBoot应用并添加依赖
pom.xml配置:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-opentelemetry</artifactId>
</dependency>
这个Starter包含了:
- OpenTelemetry API
- Micrometer桥接器
- 指标和追踪的OTLP Exporter
3.2 配置文件
application.yml:
yaml
spring:
application:
name: observability-service
management:
tracing:
sampling:
probability: 1.0 # 链路采样率,开发环境可设为100%
# OTLP导出配置
otlp:
metrics:
export:
url: http://172.16.17.100:4318/v1/metrics # 指标端点
opentelemetry:
tracing:
export:
otlp:
endpoint: http://172.16.17.100:4318/v1/traces # 链路端点
logging:
export:
otlp:
endpoint: http://172.16.17.100:4318/v1/logs # 日志端点
注意 :
192.168.137.100是LGTM系统所在服务器的IP地址,请根据实际情况修改。
3.3 创建测试Controller
java
import io.opentelemetry.api.trace.Span;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/api")
public class DemoController {
@GetMapping(path = "/demo")
public String demo() {
// 获取当前Span的Trace和Span信息
String traceId = Span.current().getSpanContext().getTraceId();
String spanId = Span.current().getSpanContext().getSpanId();
// 日志中自动关联Trace信息
log.info("DemoController demo, trace:{}, spanId:{}", traceId, spanId);
return "demo - " + traceId;
}
}
运行后控制台输出示例:
2026-02-05T14:30:22.314+08:00 INFO [...]
[a7a1b41bae7e3e0e4a9325e18dc41fb6-a6a00945436b94b5]
c.g.x.s.controller.DemoController: DemoController demo,
trace:a7a1b41bae7e3e0e4a9325e18dc41fb6, spanId:a6a00945436b94b5
可以看到日志中自动包含了Trace ID和Span ID,格式为[traceId-spanId]。
四、在Grafana中查看可观测性数据
4.1 查看链路追踪(Tempo)
- 访问Grafana:http://172.16.17.100:3000
- 点击左侧菜单"Explore"
- 选择数据源"Tempo"
- 查询类型选择"Search"
- 点击"Run Query"查看所有链路
Grafana操作流程
登录Grafana
选择Explore
选择数据源Tempo
选择Search查询
查看链路列表
点击traceId查看详情
链路详情页面包含:
- 完整的调用链视图
- 每个Span的耗时统计
- Span的标签和事件信息
- 服务间调用关系
4.2 查看指标(Prometheus)
- 在Explore页面选择数据源"Prometheus"
- 在Metrics浏览器中选择指标(如
http_server_requests_seconds_count) - 设置过滤条件(如
service_name="observability-service") - 点击"Run Query"查看指标图表
常用指标:
http_server_requests_seconds_count:HTTP请求计数jvm_memory_used_bytes:JVM内存使用process_cpu_usage:CPU使用率
4.3 配置日志上传
4.3.1 添加日志依赖
xml
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-logback-appender-1.0</artifactId>
<version>2.25.0-alpha</version>
</dependency>
4.3.2 配置Logback
创建src/main/resources/logback-spring.xml:
xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 包含Spring Boot默认的控制台日志配置 -->
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<!-- 配置OpenTelemetry日志Appender -->
<appender name="OTEL"
class="io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender">
</appender>
<!-- 根日志级别和Appender配置 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/> <!-- 控制台输出 -->
<appender-ref ref="OTEL"/> <!-- OTEL导出 -->
</root>
</configuration>
4.3.3 安装OpenTelemetry Appender
java
import io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender;
import io.opentelemetry.api.OpenTelemetry;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class InstallOpenTelemetryAppender implements InitializingBean {
private final OpenTelemetry openTelemetry;
public InstallOpenTelemetryAppender(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
}
@Override
public void afterPropertiesSet() {
// 将OpenTelemetry实例安装到Appender中
OpenTelemetryAppender.install(this.openTelemetry);
}
}
4.4 在Grafana中查看日志
-
在Explore页面选择数据源"Loki"
-
使用LogQL查询语法过滤日志:
{service_name="observability-service"} |= "DemoController" -
点击"Run Query"查看日志
关键特性:点击日志中的traceId可以直接跳转到Tempo中的完整链路详情,实现日志与链路的无缝关联。
是
否
查看Loki日志
日志包含traceId?
点击traceId链接
自动跳转到Tempo
查看完整调用链
普通日志查看
五、核心优势总结
5.1 与传统Actuator方案对比
| 特性 | SpringBoot 4.0 + OpenTelemetry | 传统Actuator + Micrometer |
|---|---|---|
| 协议标准 | OTLP(OpenTelemetry标准) | 各后端自定义协议 |
| 数据模型 | 统一的数据模型(Logs/Metrics/Traces) | 分散的数据模型 |
| 后端兼容性 | 任何支持OTLP的后端 | 需为不同后端配置不同Exporter |
| 关联性 | 原生支持Trace与Log关联 | 需手动实现关联 |
| 学习曲线 | 平缓,标准统一 | 较陡,需学习多种Exporter配置 |
5.2 三大支柱完美统一
- 统一的数据出口:全部通过OTLP协议发送
- 统一的上下文传播:Trace信息自动注入日志
- 统一的UI展示:Grafana一站式查询
六、生产环境建议
6.1 采样率配置
yaml
management:
tracing:
sampling:
probability: 0.1 # 生产环境建议10%采样率
6.2 资源限制
在docker-compose中添加资源限制:
yaml
services:
grafana-lgtm:
image: 'grafana/otel-lgtm:latest'
ports:
- '3000:3000'
- '4317:4317'
- '4318:4318'
deploy:
resources:
limits:
memory: 4G
reservations:
memory: 2G
6.3 持久化配置
为LGTM组件配置数据持久化:
yaml
services:
grafana-lgtm:
image: 'grafana/otel-lgtm:latest'
ports:
- '3000:3000'
- '4317:4317'
- '4318:4318'
volumes:
- ./data/prometheus:/data/prometheus
- ./data/tempo:/data/tempo
- ./data/loki:/data/loki
- ./data/grafana:/var/lib/grafana
七、总结
SpringBoot 4.0通过spring-boot-starter-opentelemetry为开发者提供了一套标准化、一体化、易集成的可观测性解决方案:
- 标准化:基于OpenTelemetry标准,拥抱行业未来
- 一体化:三大支柱统一出口、统一模型、统一上下文
- 易集成:SpringBoot Starter简化配置,与框架无缝集成
- 强关联:Trace与Log自动关联,问题排查效率倍增
通过本文的实践,您可以快速搭建一套完整的可观测性系统,让生产环境真正变得"可见"。
扩展阅读:
注:本文基于Spring 7.0/SpringBoot 4.0预览版特性编写,最终发布版本可能略有调整。