Spring Boot 高并发优化是一个系统性工程,需从 架构设计、容器配置、代码优化、缓存策略、数据库调优、异步处理、限流熔断 等多个维度入手,结合业务场景分层优化。以下是具体的优化方向和实践方案:
一、基础环境与容器优化
1. JVM 调优(核心)
高并发下 JVM 性能直接影响系统稳定性,重点优化垃圾回收(GC)和内存分配:
- 内存分配:合理设置堆内存(-Xms=-Xmx,避免动态扩容消耗),例如 8G 服务器设置 -Xms4g -Xmx4g(预留系统和非堆内存)。新生代(Eden + Survivor)比例调整:高并发场景下对象创建销毁频繁,提议新生代占堆的 1/3~1/2(-XX:NewRatio=2 表明新生代:老年代 = 1:2)。避免大对象直接进入老年代(-XX:PretenureSizeThreshold=1048576,1MB 以上大对象直接入老年代,减少新生代 GC 压力)。
- GC 收集器选择:JDK 8+ 优先使用 G1 GC(低延迟、高吞吐量),配置:-XX:+UseG1GC -XX:MaxGCPauseMillis=200(目标停顿时间 200ms)。超大规模堆(16G+)可尝试 ZGC/Shenandoah GC(毫秒级停顿,JDK 11+ 支持)。
- 避免 GC 频繁:监控 GC 日志(-XX:+PrintGCDetails -XX:+PrintGCTimeStamps),排查内存泄漏(如静态集合未释放、长生命周期对象持有短对象引用)。
2. Tomcat 容器优化(默认嵌入式容器)
Spring Boot 默认使用 Tomcat,高并发下需调整线程池和连接参数(application.yml):
server:
tomcat:
max-threads: 200 # 核心线程池最大线程数(根据 CPU 核心数调整,一般 CPU*2+1)
min-spare-threads: 50 # 核心线程数(保持空闲线程,避免频繁创建销毁)
max-connections: 10000 # 最大并发连接数(超出后排队)
accept-count: 1000 # 等待队列大小(超出后拒绝连接)
connection-timeout: 2000 # 连接超时时间(毫秒)
port: 8080
undertow: # 若替换为 Undertow(非阻塞,性能更优),配置如下
io-threads: 8 # IO 线程数(等于 CPU 核心数)
worker-threads: 256 # 工作线程数(CPU*32)
buffer-size: 16384 # 缓冲区大小
- 替换容器:高并发场景推荐用 Undertow(非阻塞 IO,内存占用低)或 Jetty,只需排除 Tomcat 依赖,引入对应依赖:
<!-- 排除 Tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入 Undertow -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
二、代码层面优化
1. 无状态设计(支持水平扩展)
- 服务层、控制层避免使用 静态变量、ThreadLocal(非必要不使用)、成员变量存储请求上下文,确保每个请求独立,支持多实例部署。
- 若需共享状态,使用 Redis、ZooKeeper 等分布式存储,避免本地缓存一致性问题。
2. 异步处理(提升吞吐量)
高并发下同步请求会阻塞线程,通过异步化释放线程资源,处理更多请求:
- @Async 异步方法:主启动类添加 @EnableAsync 开启异步。异步方法添加 @Async(需定义在独立 Bean 中,避免循环依赖)。配置线程池(默认线程池过小,易耗尽):
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20); // 核心线程数
executor.setMaxPoolSize(100); // 最大线程数
executor.setQueueCapacity(1000); // 队列容量
executor.setKeepAliveSeconds(60); // 空闲线程存活时间
executor.setThreadNamePrefix("AsyncTask-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略(避免丢弃任务)
return executor;
}
}
- 异步 Controller:使用 DeferredResult 或 Callable 处理 HTTP 异步请求,支持长连接(如消息推送、实时查询):
@GetMapping("/async-query")
public DeferredResult<String> asyncQuery() {
DeferredResult<String> result = new DeferredResult<>(3000L, "超时"); // 3秒超时
// 异步处理业务(如调用第三方接口、数据库查询)
asyncService.process(result);
return result;
}
3. 避免阻塞操作(减少线程占用)
- 数据库查询:使用 JPA/Hibernate 的 @Async 查询,或 MyBatis 的异步 mapper(@MapperScan 配合 SqlSessionFactory 异步配置)。
- 第三方接口调用:使用异步 HTTP 客户端(如 OkHttp3 异步模式、Spring Cloud OpenFeign 的 @Async 支持),避免同步等待响应。
- 文件 IO:使用 NIO 非阻塞 IO(java.nio.file),避免传统 FileInputStream 阻塞线程。
4. 减少锁竞争(提升并发度)
- 避免使用 synchronized 修饰大范围方法,优先使用 细粒度锁(如 ReentrantLock 锁定局部资源)。
- 高并发读场景使用 读写锁(ReentrantReadWriteLock),支持多线程读、单线程写。
- 无状态场景避免锁,用 原子类(AtomicInteger、AtomicReference) 替代锁操作。
三、缓存策略优化(减轻数据库压力)
缓存是高并发优化的核心,通过缓存热点数据,减少数据库查询次数:
1. 本地缓存(Caffeine)
- 本地缓存速度最快,适合缓存高频访问、无状态、不变的数据(如字典、配置)。
- 推荐使用 Caffeine(性能优于 Guava Cache),结合 Spring Cache 注解使用:
<!-- 引入依赖 -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
spring:
cache:
type: caffeine
caffeine:
spec: maximumSize=10000,expireAfterWrite=300s # 最大10000条,300秒过期
@Service
@CacheConfig(cacheNames = "dictCache")
public class DictService {
@Cacheable(key = "#code") // 缓存命中直接返回,未命中执行方法并缓存
public String getDictValue(String code) {
return dictMapper.selectByCode(code); // 数据库查询
}
}
2. 分布式缓存(Redis)
- 多实例部署时,本地缓存无法共享,需使用 Redis 作为分布式缓存,缓存热点数据(如用户信息、商品详情)。
- 优化点:序列化:使用 Jackson2JsonRedisSerializer 替代默认的 JdkSerializationRedisSerializer(体积小、可读性强)。过期策略:设置合理的过期时间(避免缓存雪崩),结合 随机过期时间(如 300s + 随机10s)。缓存穿透:使用 布隆过滤器 过滤不存在的 key(如 RedisBloom),避免缓存和数据库都被穿透。缓存击穿:热点 key 过期时,使用 互斥锁(Redis SETNX) 或 永不过期 + 后台更新 避免并发查询数据库。缓存雪崩:批量 key 过期时,分散过期时间; Redis 集群部署(主从 + 哨兵)避免单点故障。
四、数据库调优(高并发瓶颈核心)
数据库是高并发场景的主要瓶颈,需从 连接池、索引、SQL、分库分表 优化:
1. 数据库连接池优化
- 使用 HikariCP(Spring Boot 2.x 默认,性能最优),配置合理的连接数:
- yaml
- spring: datasource: hikari: maximum-pool-size: 20 # 最大连接数(根据数据库最大连接数调整,如 MySQL 默认151) minimum-idle: 5 # 最小空闲连接数 idle-timeout: 300000 # 空闲连接超时时间(5分钟) connection-timeout: 30000 # 连接超时时间(30秒) max-lifetime: 1800000 # 连接最大生命周期(30分钟,避免长时间连接失效)
- 核心原则:连接池最大连接数 ≤ 数据库最大连接数(MySQL 可通过 show variables like 'max_connections' 查看)。
2. 索引优化
- 给查询频繁的字段(WHERE、JOIN、ORDER BY)建立索引,避免全表扫描。
- 避免过度索引(索引会降低插入 / 更新性能),优先使用 联合索引(遵循最左前缀原则)。
- 定期分析慢查询(开启 MySQL 慢查询日志,slow_query_log=1,long_query_time=1),优化无索引或索引失效的 SQL。
3. SQL 优化
- 避免 SELECT *,只查询必要字段。
- 避免 JOIN 过多表(提议不超过 3 张),复杂查询拆分多个简单查询。
- 批量操作:使用 batchInsert/batchUpdate(MyBatis 批量插入需设置 rewriteBatchedStatements=true)。
- 分页优化:MySQL 大分页用 WHERE id > 上一页最大id 替代 LIMIT offset, size(避免全表扫描)。
4. 分库分表(数据量超千万)
- 水平分表:按用户 ID、时间等字段分片(如 Sharding-JDBC),分散单表数据量。
- 垂直分表:将大表拆分为小表(如用户表拆分为用户基本信息表、用户详情表),减少字段冗余。
- 分库:按业务模块分库(如订单库、用户库),分散数据库压力。
5. 读写分离
- 主库写入,从库查询(如 MySQL 主从复制),通过 Sharding-JDBC 或 MyCat 实现读写分离,减轻主库压力。
五、架构层面优化
1. 水平扩展(集群部署)
- 无状态服务多实例部署,通过 Nginx 或 Spring Cloud Gateway 负载均衡(轮询、加权轮询、IP 哈希)分发请求。
- 负载均衡优化:根据实例性能调整权重(如高性能服务器权重更高),避免单点过载。
2. 限流熔断(保护系统不被压垮)
- 限流:限制单位时间内的请求数,避免流量峰值击垮系统。方案:Spring Cloud Gateway + Sentinel/Resilience4j,或 Nginx 限流(limit_req_zone)。粒度:接口级、用户级、IP 级限流(如秒杀接口限制 1000 QPS)。
- 熔断:当依赖服务(如数据库、第三方接口)故障时,快速失败并返回降级结果,避免级联故障。工具:Resilience4j(Spring Boot 2.x 推荐,轻量级)、Sentinel(阿里开源,支持流量控制、熔断、降级)。
3. 静态资源优化
- 静态资源(JS、CSS、图片)部署到 CDN(如阿里云 CDN、七牛云),减轻应用服务器压力。
- 开启 Gzip 压缩(Nginx 或 Spring Boot 配置),减少传输体积:
server:
compression:
enabled: true
mime-types: application/json,application/xml,text/html,text/css,application/javascript
min-response-size: 1024 # 大于1KB才压缩
六、监控与压测(持续优化)
1. 监控体系
- 接入 Spring Boot Actuator 暴露监控端点(健康检查、指标统计):
- yaml
- management: endpoints: web: exposure: include: health,info,metrics,prometheus metrics: tags: application: ${spring.application.name}
- 结合 Prometheus + Grafana 监控 JVM 指标(GC、内存)、接口 QPS、响应时间、数据库连接数等。
- 日志监控:使用 ELK 栈(Elasticsearch + Logstash + Kibana)收集日志,排查高并发下的异常。
2. 压测验证
- 使用 JMeter 或 Gatling 进行压测,模拟高并发场景(如 1000 并发用户、持续 5 分钟)。
- 压测指标:QPS(每秒请求数)、响应时间(平均 / 95%/99% 响应时间)、错误率、CPU / 内存使用率。
- 优化迭代:根据压测结果定位瓶颈(如数据库慢查询、线程池耗尽、缓存未命中),针对性优化后再次压测。
总结
Spring Boot 高并发优化的核心思路是:“减少阻塞、提升并行度、分散压力”。具体可按以下步骤落地:
- 基础优化:JVM + 容器(Tomcat/Undertow)调优,确保底层稳定。
- 代码优化:异步化、无状态、减少锁竞争,提升单实例吞吐量。
- 缓存优化:本地缓存 + 分布式缓存,减轻数据库压力。
- 数据库调优:连接池、索引、SQL、分库分表,解决数据层瓶颈。
- 架构优化:水平扩展、限流熔断、CDN 静态资源,分散整体压力。
- 监控压测:持续监控指标,通过压测验证优化效果,迭代改善。
根据业务场景优先级调整优化方向(如秒杀场景优先做限流、缓存、分库分表;API 服务优先做异步、连接池优化)。
© 版权声明
文章版权归作者所有,未经允许请勿转载。



不错
系统被你压出油了
收藏了,感谢分享