找回密码
 立即注册
首页 业界区 业界 SpringBoot性能优化的12个小技巧

SpringBoot性能优化的12个小技巧

判涔 2025-6-3 00:18:30
前言

不知道你在SpringBoot项目中,有没有遇到过下面这样的代码:
  1. @GetMapping("/orders")
  2. public List<Order> listOrders() {
  3.     return orderDao.findAll();
  4. }
复制代码
一次性查询了所有的订单,全表扫描50万数据,导致接口查询性能很差,严重的时候可能会导致OOM问题。
问题定位

  • 未分页查询
  • 无缓存机制
  • 未启用批量处理
这次事故让我明白:性能优化必须贯穿开发全流程
今天这篇文章,跟大家一起聊聊SpringBoot优化的12招,希望对你会有所帮助。
1.webp

2.webp

第1招:连接池参数调优

问题场景
默认配置导致连接池资源浪费,高并发时出现连接等待
错误配置
  1. spring:
  2.   datasource:
  3.     hikari:
  4.       maximum-pool-size: 1000
  5.       connection-timeout: 30000
复制代码
数据库连接池的最大连接数,盲目设置过大,连接超时时间设置过长。
优化方案
  1. spring:
  2.   datasource:
  3.     hikari:
  4.       maximum-pool-size: ${CPU核心数*2} # 动态调整
  5.       minimum-idle: 5
  6.       connection-timeout: 3000 # 3秒超时
  7.       max-lifetime: 1800000 # 30分钟
  8.       idle-timeout: 600000 # 10分钟空闲释放
复制代码
数据库连接池的最大连接数,改成根据CPU核心数动态调整。
将连接超时时间由30000,改成3000。
第2招:JVM内存优化

问题场景
频繁Full GC导致服务卡顿
我们需要优化JVM参数。
启动参数优化
  1. java -jar -Xms4g -Xmx4g
  2. -XX:NewRatio=1
  3. -XX:+UseG1GC
  4. -XX:MaxGCPauseMillis=200
  5. -XX:InitiatingHeapOccupancyPercent=35
  6. -XX:+AlwaysPreTouch
复制代码
最大堆内存和初始堆内存都设置成了4G。
-XX:NewRatio=1,设置新生代和老年代各占一半。
垃圾收集器配置的是G1。
垃圾回收的最大停顿时间为200毫秒。
第3招:关闭无用组件

问题场景
自动装配加载不需要的Bean
优化方案
  1. @SpringBootApplication(exclude = {
  2.     DataSourceAutoConfiguration.class,
  3.     SecurityAutoConfiguration.class
  4. })
  5. public class Application {
  6.     public static void main(String[] args) {
  7.         SpringApplication.run(Application.class, args);
  8.     }
  9. }
复制代码
如果有些功能暂时用不到,可以先排除一下。
在SpringBoot项目启动的时候,排除了DataSourceAutoConfiguration和SecurityAutoConfiguration配置类的自动装载。
第4招:响应压缩配置

问题场景
接口返回JSON数据体积过大
优化方案
  1. server:
  2.   compression:
  3.     enabled: true
  4.     mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/json
  5.     min-response-size: 1024
复制代码
配置开启响应的压缩。
第5招:请求参数校验

问题场景
恶意请求导致资源耗尽
防御代码
  1. @GetMapping("/products")
  2. public PageResult<Product> list(
  3.     @RequestParam @Max(value=100, message="页大小不能超过100") int pageSize,
  4.     @RequestParam @Min(1) int pageNum) {
  5.     //...
  6. }
复制代码
在接口中做好参数校验,可以拦截很多恶意请求。
第6招:异步处理机制

问题场景
同步处理导致线程阻塞
优化方案
  1. @Async("taskExecutor")
  2. public CompletableFuture<List<Order>> asyncProcess() {
  3.     return CompletableFuture.completedFuture(heavyProcess());
  4. }
  5. @Bean("taskExecutor")
  6. public Executor taskExecutor() {
  7.     ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  8.     executor.setCorePoolSize(5);
  9.     executor.setMaxPoolSize(10);
  10.     executor.setQueueCapacity(500);
  11.     return executor;
  12. }
复制代码
在有些业务逻辑中,使用异步处理性能可能会更好。
第7招:使用缓存

使用缓存可以提升效率。
缓存架构
3.webp

代码实现
  1. @Cacheable(cacheNames = "products", key = "#id",
  2.            cacheManager = "caffeineCacheManager")
  3. public Product getDetail(Long id) {
  4.     return productDao.getById(id);
  5. }
复制代码
这里使用了内存缓存。
第8招:批量操作优化

问题场景
逐条插入导致性能低下
优化方案
  1. @Transactional
  2. public void batchInsert(List<Product> products) {
  3.     jdbcTemplate.batchUpdate(
  4.         "INSERT INTO product(name,price) VALUES(?,?)",
  5.         products,
  6.         500, // 每批数量
  7.         (ps, product) -> {
  8.             ps.setString(1, product.getName());
  9.             ps.setBigDecimal(2, product.getPrice());
  10.         });
  11. }
复制代码
每500条数据插入一次数据库。
第9招:索引深度优化

问题场景
慢查询日志频繁出现全表扫描,SQL执行时间波动大
错误案例
  1. -- 商品表结构
  2. CREATE TABLE products (
  3.     id BIGINT PRIMARY KEY,
  4.     name VARCHAR(200),
  5.     category VARCHAR(50),
  6.     price DECIMAL(10,2),
  7.     create_time DATETIME
  8. );
  9. -- 低效查询
  10. SELECT * FROM products
  11. WHERE category = '手机'
  12. AND price > 5000
  13. ORDER BY create_time DESC;
复制代码
问题分析
4.webp

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

索引创建
下面创建了一个分类ID,单价和时间的联合索引:
  1. ALTER TABLE products
  2. ADD INDEX idx_category_price_create
  3. (category, price, create_time);
复制代码
优化方案二:覆盖索引优化

查询改造
只查询索引包含字段:
  1. SELECT id, category, price, create_time
  2. FROM products
  3. WHERE category = '手机'
  4. AND price > 5000
  5. ORDER BY create_time DESC;
复制代码
这里使用了覆盖索引。
优化方案三:索引失效预防

常见失效场景
5.webp

案例修复
错误写法:
  1. SELECT * FROM products
  2. WHERE DATE(create_time) = '2023-01-01';
复制代码
正确写法:
  1. SELECT * FROM products
  2. WHERE create_time BETWEEN '2023-01-01 00:00:00'
  3. AND '2023-01-01 23:59:59';
复制代码
查询时间范围,这里使用了BETWEEN AND关键字,代替了等于号。
优化方案四:索引监控分析

诊断命令
查看索引使用情况:
  1. SELECT
  2.     index_name,
  3.     rows_read,
  4.     rows_selected
  5. FROM
  6.     sys.schema_index_statistics
  7. WHERE
  8.     table_name = 'products';
复制代码
分析索引效率:
  1. EXPLAIN FORMAT=JSON
  2. SELECT ...;
复制代码
索引优化黄金三原则


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

  • 索引分析脚本
  • 执行计划可视化工具
  • 索引碎片检测工具
第10招:自定义线程池

问题场景
默认线程池导致资源竞争
优化方案
  1. @Bean("customPool")
  2. public Executor customThreadPool() {
  3.     return new ThreadPoolExecutor(
  4.         10, // 核心线程
  5.         50, // 最大线程
  6.         60, TimeUnit.SECONDS,
  7.         new LinkedBlockingQueue<>(1000),
  8.         new CustomThreadFactory(),
  9.         new ThreadPoolExecutor.CallerRunsPolicy());
  10. }
复制代码
在高并发业务场景中,使用Executors类创建默认的线程池,可能会导致OOM问题。
因此,我们需要自定义线程池。
第11招:熔断限流策略

问题场景
突发流量导致服务雪崩
解决方案
  1. // 使用Sentinel实现接口限流
  2. @SentinelResource(value = "orderQuery",
  3.                   blockHandler = "handleBlock",
  4.                   fallback = "handleFallback")
  5. @GetMapping("/orders/{id}")
  6. public Order getOrder(@PathVariable Long id) {
  7.     return orderService.getById(id);
  8. }
  9. // 限流处理
  10. public Order handleBlock(Long id, BlockException ex) {
  11.     throw new RuntimeException("服务繁忙,请稍后重试");
  12. }
  13. // 降级处理
  14. public Order handleFallback(Long id, Throwable t) {
  15.     return Order.getDefaultOrder();
  16. }
复制代码
为了解决重复流量导致服务雪崩的问题,我们需要增加接口熔断、限流和降级处理。
第12招:全链路监控体系

问题场景
线上问题定位困难,缺乏数据支撑
我们需要增加项目全链路的监控。
监控方案
  1. # SpringBoot配置
  2. management:
  3.   endpoints:
  4.     web:
  5.       exposure:
  6.         include: "*"
  7.   metrics:
  8.     export:
  9.       prometheus:
  10.         enabled: true
复制代码
这里使用了prometheus监控。
监控架构
6.webp

核心监控指标
7.webp

总结

SpringBoot性能优化检查清单


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

三条黄金法则

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

  • Arthas在线诊断
  • JProfiler性能分析
  • Prometheus监控体系
(看着监控大屏上平稳的QPS曲线,我知道今晚可以睡个好觉了...)
最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,我的所有文章都会在公众号上首发,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。
本文收录于我的技术网站:http://www.susan.net.cn

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册