Spring Boot 3.x 性能优化终极指南


Spring Boot 3.x 性能优化终极指南

概述

Spring Boot 3.x 基于 Spring Framework 6 和 Jakarta EE,带来了显著的性能提升。本文深入探讨如何最大化应用性能。

JVM 层面优化

1. 选择合适的垃圾回收器

G1GC(推荐)

java -jar app.jar \ -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 \ -XX:G1HeapRegionSize=16m

适用场景:大堆内存(4GB+),需要低延迟

ZGC(Java 21+)

java -jar app.jar \ -XX:+UseZGC \ -XX:+ZGenerational

适用场景:超低延迟要求(<10ms GC 暂停)

2. 内存调优

堆内存设置

# 初始堆和最大堆设为相同值 java -Xms4g -Xmx4g -jar app.jar # 元空间 java -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m

直接内存

# 限制直接内存,防止 OOM java -XX:MaxDirectMemorySize=1g

3. JIT 编译优化

# 分层编译(默认) java -XX:+TieredCompilation # 提前优化 java -XX:CompileThreshold=10000 # 使用 C2 编译器 java -XX:+UseCompressedOops

Spring Boot 配置优化

1. 应用配置

application-prod.yml

spring: # 关闭开发时功能 devtools: restart: enabled: false # 生产环境配置 jpa: show-sql: false open-in-view: false # Jackson 优化 jackson: default-property-inclusion: non_null serialization: write-dates-as-timestamps: false # 日志配置 logging: level: root: INFO org.springframework: WARN pattern: console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"

2. 线程池优化

Tomcat 线程池

server: tomcat: threads: max: 200 min-spare: 10 max-connections: 10000 accept-count: 100

异步任务线程池

@Configuration @EnableAsync public class AsyncConfig { @Bean(name = "taskExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(50); executor.setQueueCapacity(100); executor.setThreadNamePrefix("async-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } }

3. 数据库连接池优化

HikariCP(默认)

spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 idle-timeout: 30000 max-lifetime: 1200000 connection-timeout: 30000 pool-name: "HikariPool"

性能监控

@Bean public DataSource dataSource(DataSourceProperties properties) { HikariDataSource dataSource = properties .initializeDataSourceBuilder() .type(HikariDataSource.class) .build(); // 启用 JMX 监控 dataSource.setMetricRegistry(metricRegistry); return dataSource; }

数据库优化

1. SQL 优化

使用索引

-- 创建复合索引 CREATE INDEX idx_user_email_status ON users(email, status); -- 覆盖索引 CREATE INDEX idx_order_user_status ON orders(user_id, status, created_at);

避免 N+1 查询

// ❌ 不好的做法 List<User> users = user.findAll(); for (User user : users) { List<Order> orders = order.findByUserId(user.getId()); } // ✅ 好的做法(JOIN FETCH) @Query("SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :id") User findByIdWithOrders(@Param("id") Long id); // ✅ 或使用 EntityGraph @EntityGraph(attributePaths = {"orders"}) User findById(Long id);

2. 批量操作

JPA Batch Insert

spring: jpa: properties: hibernate: jdbc: batch_size: 50 order_inserts: true order_updates: true
@Transactional public void batchInsert(List<User> users) { for (int i = 0; i < users.size(); i++) { entityManager.persist(users.get(i)); // 定期 flush 和 clear if (i % 50 == 0) { entityManager.flush(); entityManager.clear(); } } }

3. 查询缓存

启用二级缓存

spring: jpa: properties: hibernate: cache: use_second_level_cache: true region: factory_class: jcache
@Cacheable @CacheRegion("users") @Entity public class User { // ... }

缓存策略

1. Spring Cache

Redis 配置

@Configuration @EnableCaching public class CacheConfig { @Bean public RedisCacheManager cacheManager(RedisConnectionFactory factory) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(10)) .disableCachingNullValues() .serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer( new GenericJackson2JsonRedisSerializer() ) ); return RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); } }

缓存注解

@Service public class UserService { @Cacheable(value = "users", key = "#id") public User findById(Long id) { return userRepository.findById(id).orElse(null); } @CacheEvict(value = "users", key = "#user.id") public User update(User user) { return userRepository.save(user); } @CacheEvict(value = "users", allEntries = true) public void clearCache() { // 清空所有缓存 } }

2. 本地缓存

Caffeine(推荐)

@Bean public Cache<String, Object> localCache() { return Caffeine.newBuilder() .maximumSize(10000) .expireAfterWrite(Duration.ofMinutes(5)) .recordStats() .build(); }

异步处理

1. @Async 注解

@Service public class EmailService { @Async("taskExecutor") public void sendEmail(String to, String subject, String body) { // 异步发送邮件 mailSender.send(to, subject, body); } }

2. Spring WebFlux(响应式)

@RestController public class ReactiveUserController { private final UserRepository userRepository; @GetMapping("/users/{id}") public Mono<User> getUser(@PathVariable Long id) { return userRepository.findById(id); } @GetMapping("/users") public Flux<User> getAllUsers() { return userRepository.findAll(); } }

静态资源优化

1. 资源压缩

server: compression: enabled: true mime-types: text/html,text/xml,text/plain,text/css,application/javascript,application/json

2. 缓存控制

@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**") .addResourceLocations("classpath:/static/") .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS)); } }

监控与分析

1. Actuator 配置

management: endpoints: web: exposure: include: health,info,metrics,prometheus metrics: export: prometheus: enabled: true

2. 自定义指标

@Component public class MetricsConfig { private final MeterRegistry meterRegistry; public void recordApiCall(String endpoint, long duration) { Timer.builder("api.call.duration") .tag("endpoint", endpoint) .register(meterRegistry) .record(duration, TimeUnit.MILLISECONDS); } }

3. 分布式追踪

<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-tracing-bridge-brave</artifactId> </dependency> <dependency> <groupId>io.zipkin.reporter2</groupId> <artifactId>zipkin-reporter-brave</artifactId> </dependency>
management: tracing: sampling: probability: 1.0 zipkin: tracing: endpoint: http://zipkin:9411/api/v2/spans

性能测试

1. JMeter

  • 并发用户测试
  • 负载测试
  • 压力测试

2. Gatling

// 性能测试脚本 val httpProtocol = http.baseUrl("http://localhost:8080") val scn = scenario("User Scenario") .exec(http("get_users") .get("/api/users") .check(status.is(200))) setUp( scn.inject( rampUsersPerSec(10) to 100 during (60 seconds) ) ).protocols(httpProtocol)

常见性能瓶颈

1. 数据库慢查询

  • 添加索引
  • 优化 SQL
  • 使用缓存

2. 内存泄漏

  • 使用 VisualVM 分析
  • 检查 ThreadLocal
  • 注意静态集合

3. 线程池耗尽

  • 合理设置线程池大小
  • 使用异步处理
  • 拒绝策略优化

最佳实践总结

  1. JVM 调优:选择合适的 GC 和内存设置
  2. 连接池:优化数据库和 HTTP 连接池
  3. 缓存策略:多级缓存,合理设置 TTL
  4. 异步处理:提高吞吐量
  5. 监控告警:及时发现性能问题
  6. 持续优化:性能是迭代过程

记住:过早优化是万恶之源,先测量再优化!


作者与出处
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天学者_SSSV45的小龙虾 转发
评论区 (0)
U