⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 苏三说技术 「苏三」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

前言

不知道你在SpringBoot项目中,有没有遇到过下面这样的代码:

@GetMapping("/orders")
public List<Order> listOrders() {
return orderDao.findAll();
}

一次性查询了所有的订单,全表扫描50万数据,导致接口查询性能很差,严重的时候可能会导致OOM问题。

问题定位:

  • 未分页查询
  • 无缓存机制
  • 未启用批量处理

这次事故让我明白:性能优化必须贯穿开发全流程。

今天这篇文章,跟大家一起聊聊SpringBoot优化的12招,希望对你会有所帮助。

第1招:连接池参数调优

问题场景:
默认配置导致连接池资源浪费,高并发时出现连接等待

错误配置:

spring:
datasource:
hikari:
maximum-pool-size: 1000
connection-timeout: 30000

数据库连接池的最大连接数,盲目设置过大,连接超时时间设置过长。

优化方案:

spring:
datasource:
hikari:
maximum-pool-size: ${CPU核心数*2} # 动态调整
minimum-idle: 5
connection-timeout: 3000 # 3秒超时
max-lifetime: 1800000 # 30分钟
idle-timeout: 600000 # 10分钟空闲释放

数据库连接池的最大连接数,改成根据CPU核心数动态调整。

将连接超时时间由30000,改成3000。

第2招:JVM内存优化

问题场景:
频繁Full GC导致服务卡顿

我们需要优化JVM参数。

启动参数优化:

java -jar -Xms4g -Xmx4g 
-XX:NewRatio=1
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=35
-XX:+AlwaysPreTouch

最大堆内存和初始堆内存都设置成了4G。

-XX:NewRatio=1,设置新生代和老年代各占一半。

垃圾收集器配置的是G1。

垃圾回收的最大停顿时间为200毫秒。

第3招:关闭无用组件

问题场景:
自动装配加载不需要的Bean

优化方案:

@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
SecurityAutoConfiguration.class
})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

如果有些功能暂时用不到,可以先排除一下。

在SpringBoot项目启动的时候,排除了DataSourceAutoConfiguration和SecurityAutoConfiguration配置类的自动装载。

第4招:响应压缩配置

问题场景:
接口返回JSON数据体积过大

优化方案:

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

配置开启响应的压缩。

第5招:请求参数校验

问题场景:
恶意请求导致资源耗尽

防御代码:

@GetMapping("/products")
public PageResult<Product> list(
@RequestParam @Max(value=100, message="页大小不能超过100") int pageSize,
@RequestParam @Min(1) int pageNum) {
//...
}

在接口中做好参数校验,可以拦截很多恶意请求。

第6招:异步处理机制

问题场景:
同步处理导致线程阻塞

优化方案:

@Async("taskExecutor")
public CompletableFuture<List<Order>> asyncProcess() {
return CompletableFuture.completedFuture(heavyProcess());
}

@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(500);
return executor;
}

在有些业务逻辑中,使用异步处理性能可能会更好。

第7招:使用缓存

使用缓存可以提升效率。

缓存架构:

代码实现:

@Cacheable(cacheNames = "products", key = "#id", 
cacheManager = "caffeineCacheManager")
public Product getDetail(Long id) {
return productDao.getById(id);
}

这里使用了内存缓存。

第8招:批量操作优化

问题场景:
逐条插入导致性能低下

优化方案:

@Transactional
public void batchInsert(List<Product> products) {
jdbcTemplate.batchUpdate(
"INSERT INTO product(name,price) VALUES(?,?)",
products,
500, // 每批数量
(ps, product) -> {
ps.setString(1, product.getName());
ps.setBigDecimal(2, product.getPrice());
});
}

每500条数据插入一次数据库。

第9招:索引深度优化

问题场景:
慢查询日志频繁出现全表扫描,SQL执行时间波动大

错误案例:

-- 商品表结构
CREATETABLE products (
idBIGINT PRIMARY KEY,
nameVARCHAR(200),
categoryVARCHAR(50),
price DECIMAL(10,2),
create_time DATETIME
);

-- 低效查询
SELECT * FROM products
WHEREcategory = '手机'
AND price > 5000
ORDERBY create_time DESC;

问题分析:

优化方案一:联合索引设计

索引创建:

下面创建了一个分类ID,单价和时间的联合索引:

ALTER TABLE products 
ADD INDEX idx_category_price_create
(category, price, create_time);

优化方案二:覆盖索引优化

查询改造:

只查询索引包含字段:

SELECT id, category, price, create_time 
FROM products
WHERE category = '手机'
AND price > 5000
ORDER BY create_time DESC;

这里使用了覆盖索引。

优化方案三:索引失效预防

常见失效场景:

案例修复:

错误写法:

SELECT * FROM products 
WHERE DATE(create_time) = '2023-01-01';

正确写法:

SELECT * FROM products 
WHERE create_time BETWEEN '2023-01-01 00:00:00'
AND '2023-01-01 23:59:59';

查询时间范围,这里使用了BETWEEN AND关键字,代替了等于号。

优化方案四:索引监控分析

诊断命令:

查看索引使用情况:

SELECT 
index_name,
rows_read,
rows_selected
FROM
sys.schema_index_statistics
WHERE
table_name = 'products';

分析索引效率:

EXPLAIN FORMAT=JSON 
SELECT ...;

索引优化黄金三原则

  1. 最左前缀原则:联合索引的第一个字段必须出现在查询条件中
  2. 短索引原则:整型字段优先,字符串字段使用前缀索引
  3. 适度索引原则:单个表索引数量不超过5个,总索引长度不超过表数据量30%

DBA工具箱

  • 索引分析脚本
  • 执行计划可视化工具
  • 索引碎片检测工具

第10招:自定义线程池

问题场景:
默认线程池导致资源竞争

优化方案:

@Bean("customPool")
public Executor customThreadPool() {
return new ThreadPoolExecutor(
10, // 核心线程
50, // 最大线程
60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000),
new CustomThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
}

在高并发业务场景中,使用Executors类创建默认的线程池,可能会导致OOM问题。

因此,我们需要自定义线程池。

第11招:熔断限流策略

问题场景:
突发流量导致服务雪崩

解决方案:

// 使用Sentinel实现接口限流
@SentinelResource(value = "orderQuery",
blockHandler = "handleBlock",
fallback = "handleFallback")
@GetMapping("/orders/{id}")
public Order getOrder(@PathVariable Long id) {
return orderService.getById(id);
}

// 限流处理
public Order handleBlock(Long id, BlockException ex) {
thrownew RuntimeException("服务繁忙,请稍后重试");
}

// 降级处理
public Order handleFallback(Long id, Throwable t) {
return Order.getDefaultOrder();
}

为了解决重复流量导致服务雪崩的问题,我们需要增加接口熔断、限流和降级处理。

第12招:全链路监控体系

问题场景:
线上问题定位困难,缺乏数据支撑

我们需要增加项目全链路的监控。

监控方案:

# SpringBoot配置
management:
endpoints:
web:
exposure:
include: "*"
metrics:
export:
prometheus:
enabled: true

这里使用了prometheus监控。

监控架构:

核心监控指标:

总结

SpringBoot性能优化检查清单

  • 连接池参数按业务调整
  • JVM参数经过压测验证
  • 所有查询走缓存机制
  • 批量操作替代逐条处理
  • 线程池按场景定制
  • 全链路监控覆盖

三条黄金法则:

  1. 预防性优化:编码时考虑性能影响
  2. 数据驱动:用监控指标指导优化方向
  3. 持续迭代:性能优化是持续过程

性能工具包

  • Arthas在线诊断
  • JProfiler性能分析
  • Prometheus监控体系

(看着监控大屏上平稳的QPS曲线,我知道今晚可以睡个好觉了…)

文章目录
  1. 1. 前言
  2. 2. 第1招:连接池参数调优
  3. 3. 第2招:JVM内存优化
  4. 4. 第3招:关闭无用组件
  5. 5. 第4招:响应压缩配置
  6. 6. 第5招:请求参数校验
  7. 7. 第6招:异步处理机制
  8. 8. 第7招:使用缓存
  9. 9. 第8招:批量操作优化
  10. 10. 第9招:索引深度优化
    1. 10.0.1. 优化方案一:联合索引设计
    2. 10.0.2. 优化方案二:覆盖索引优化
    3. 10.0.3. 优化方案三:索引失效预防
    4. 10.0.4. 优化方案四:索引监控分析
    5. 10.0.5. 索引优化黄金三原则
  • 11. 第10招:自定义线程池
  • 12. 第11招:熔断限流策略
  • 13. 第12招:全链路监控体系
  • 14. 总结
    1. 14.0.1. SpringBoot性能优化检查清单