简单聊聊SpringBoot性能优化的12个小技巧

 更新时间:2025年05月26日 08:14:24   作者:苏三说技术  
这篇文章主要想来和大家简单聊聊SpringBoot性能优化的12个小技巧,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解一下

前言

不知道你在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执行时间波动大

错误案例

-- 商品表结构
CREATE TABLE products (
    id BIGINT PRIMARY KEY,
    name VARCHAR(200),
    category VARCHAR(50),
    price DECIMAL(10,2),
    create_time DATETIME
);

-- 低效查询
SELECT * FROM products 
WHERE category = '手机' 
AND price > 5000 
ORDER BY 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 ...;

索引优化黄金三原则

  • 最左前缀原则:联合索引的第一个字段必须出现在查询条件中
  • 短索引原则:整型字段优先,字符串字段使用前缀索引
  • 适度索引原则:单个表索引数量不超过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) {
    throw new 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参数经过压测验证
  • 所有查询走缓存机制
  • 批量操作替代逐条处理
  • 线程池按场景定制
  • 全链路监控覆盖

三条黄金法则

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

性能工具包

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

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

到此这篇关于简单聊聊SpringBoot性能优化的12个小技巧的文章就介绍到这了,更多相关SpringBoot性能优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring中的编程式事务和声明式事务

    Spring中的编程式事务和声明式事务

    Spring框架中,事务管理可以通过编程式事务和声明式事务两种方式实现,编程式事务通过手动编码控制事务的开始、提交和回滚,允许开发者精确控制事务,但增加了代码复杂度,声明式事务则通过@EnableTransactionManagement注解启用事务管理
    2024-11-11
  • SpringBoot实现Md5对数据库数据加密的示例

    SpringBoot实现Md5对数据库数据加密的示例

    本文主要介绍了SpringBoot实现Md5对数据库数据加密的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Java语言实现扫雷游戏(2)

    Java语言实现扫雷游戏(2)

    这篇文章主要为大家详细介绍了Java语言实现扫雷游戏第二部分代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • 使用@ControllerAdvice同时配置过滤多个包

    使用@ControllerAdvice同时配置过滤多个包

    这篇文章主要介绍了使用@ControllerAdvice同时配置过滤多个包的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • servlet之session工作原理简介_动力节点Java学院整理

    servlet之session工作原理简介_动力节点Java学院整理

    这篇文章主要介绍了servlet之session工作原理简介,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • java中的OPT算法实现方式

    java中的OPT算法实现方式

    这篇文章主要介绍了java中的OPT算法实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • javaweb实战之商城项目开发(三)

    javaweb实战之商城项目开发(三)

    这篇文章主要针对javaweb商城项目开发进行实战演习,主要实现通用的BaseDao.java和使用resultMap映射关联对象,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • Spring Cloud升级最新Finchley版本的所有坑

    Spring Cloud升级最新Finchley版本的所有坑

    这篇文章主要介绍了Spring Cloud升级最新Finchley版本的所有坑,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Java下载文件的四种方式详细代码

    Java下载文件的四种方式详细代码

    这篇文章介绍了Java下载文件的四种方式,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • Spring Lifecycle的使用小结

    Spring Lifecycle的使用小结

    这篇文章主要介绍了Spring Lifecycle的使用,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05

最新评论