上个月帮一个团队做上线前的Code Review,翻了12个Spring Boot项目,有9个项目的核心配置项是默认的。开发用默认配置在本地跑得好好的,扔到生产就炸——Tomcat线程数200不够、HikariCP连接池10个不够、Actuator全暴露被扫描、Druid慢SQL没人看。

任何一个配置项,单独看都不致命。但高并发场景下,这些配置项中的任何一个缺失,都会直接导致502

这不是配置"调优"的问题,是配置"有没有"的问题。下面5项是Spring Boot上线前的最低配置项清单,每一项都有血淋淋的案例。

1

Tomcat线程数:默认200?大促直接排队到超时

事故场景:某电商大促峰值QPS 3000,服务从200线程的Tomcat里拿出400个线程处理请求——结果有300+个请求在队列里等着,排队超过2秒直接超时。监控显示:Tomcat线程池使用率100%,accept-count队列从50个满到500个。

默认配置的问题

# Spring Boot 2.x 默认值
server.tomcat.threads.max=200      # 最大工作线程
server.tomcat.max-connections=8192  # 最大连接数
server.tomcat.accept-count=100      # 等待队列长度
server.tomcat.connection-timeout=5s # 连接超时

# 大促场景:200线程处理3000 QPS,每个请求平均100ms
# → 200 / 0.1 = 2000 QPS上限
# → 峰值3000 QPS直接超出40%

正确配置(按业务估算)

# 业务侧需求:峰值QPS 3000,平均响应时间 100ms
# 最低线程数 = 3000 × 0.1 = 300个
# 建议值:按峰值QPS × 平均RT的1.5倍配置,留出30%buffer

server.tomcat.threads.max=500       # 峰值时段留buffer
server.tomcat.min-spare-threads=50  # 最小空闲线程,避免冷启动排队
server.tomcat.max-connections=10000 # 略大于Tomcat线程数
server.tomcat.accept-count=200      # 队列不能太长,太长等于502
server.tomcat.connection-timeout=10s

经验值:Tomcat线程数 = 峰值QPS × 平均RT × 1.5。3000 QPS × 0.1s × 1.5 = 450个,至少配到500。不要拍脑袋配200,那是开发机的值。

2

HikariCP连接池:默认10?QPS超过50就排队

事故场景:某金融系统上线后白天正常,一到晚上批量任务时段QPS从30涨到80,HikariCP连接池使用率持续100%,慢SQL数量从1条/小时涨到200+条/小时。监控显示:getConnection()等待时间从2ms涨到800ms。

默认配置的问题

# Spring Boot 2.x 默认值(HikariCP)
spring.datasource.hikari.maximum-pool-size=10    # 池大小
spring.datasource.hikari.minimum-idle=10         # 最小空闲
spring.datasource.hikari.connection-timeout=30000 # 30秒
spring.datasource.hikari.idle-timeout=600000     # 10分钟
spring.datasource.hikari.max-lifetime=1800000    # 30分钟

# 问题:10个连接,假设每个查询100ms
# → 10 / 0.1 = 100 QPS上限
# → 超过100 QPS的请求开始等待连接 → 慢SQL

正确配置(按数据库能力估算)

# 先查数据库最大连接数:show variables like 'max_connections';
# 一般MySQL默认151个,全部分给业务大概有120个可用
# 单实例应用:池大小 ≤ 30(留buffer给其他应用)
# 多实例应用:池大小 = 总可用连接数 / 实例数 - 5

spring.datasource.hikari.maximum-pool-size=30      # 单实例不超过30
spring.datasource.hikari.minimum-idle=10           # 保留10个空闲
spring.datasource.hikari.connection-timeout=3000   # 3秒拿不到连接直接报错
spring.datasource.hikari.idle-timeout=300000       # 5分钟回收空闲
spring.datasource.hikari.max-lifetime=1200000      # 20分钟强制重建,避免数据库单方面断开
spring.datasource.hikari.leak-detection-threshold=30000 # 30秒未释放视为泄漏

HikariCP官方建议池大小 = ((核心数 × 2) + 1) 个硬盘连接数,但实际按数据库承载能力配更合理。MySQL默认151连接,20个实例 × 30连接 = 600?不行,MySQL扛不住。单个应用连接池 ≤ 数据库max_connections的30%

3

Actuator端点:全暴露?等于把数据库连接池监控送人

事故场景:某团队Actuator端点暴露在公网,/actuator/env直接返回数据库密码、Redis密码、JWT密钥。安全扫描工具10秒扫到,30分钟内被脱裤。事后复盘:开发说"我以为默认就是不暴露的",实际上Spring Boot 2.x之后默认就暴露/actuator/health和/actuator/info,而/actuator/*全暴露是开发本地配置的。

默认配置的问题

# Spring Boot 2.x 之后,Actuator只暴露health和info
# 但很多人为了"方便"会写:
management.endpoints.web.exposure.include=*  # ⚠️ 全暴露!

# 等于把下面这些全部开放到公网:
# /actuator/env          → 环境变量(含数据库密码)
# /actuator/configprops  → 完整配置(含明文密码)
# /actuator/beans        → 所有Bean
# /actuator/mappings     → 所有URL映射
# /actuator/threaddump   → 线程栈(含业务逻辑)
# /actuator/heapdump     → 完整内存镜像

正确配置(最小暴露原则)

# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus  # 只暴露监控需要的
        exclude: env,configprops,beans,mappings,threaddump,heapdump
  endpoint:
    health:
      show-details: never  # 不显示详细信息,只返回UP/DOWN
  server:
    address: 127.0.0.1  # 关键!Actuator只监听本地,通过Prometheus从本地拉

# 或者放到内网端口,不走主端口
management.server.port: 9090
management.server.address: 10.0.0.0/8  # 只允许内网访问

Actuator的heapdump端点是最危险的——它返回完整JVM堆内存镜像,里面有所有缓存的密码、用户token。绝对不能暴露在公网,必须限制访问来源IP

4

日志级别:默认INFO?生产环境全打就完了

事故场景:某团队从DEBUG切回INFO时漏改了一个第三方库的level,MyBatis的SQL日志每天打500MB,一周后磁盘写满服务挂了。更极端的案例:把整个Spring Framework的日志级别配成DEBUG,单服务每天日志量8GB。

默认配置的问题

# Spring Boot默认root level = INFO
# 但很多团队没显式配,导致:
# 1. 业务代码的DEBUG也漏出来
# 2. 第三方库(Spring/MyBatis/HikariCP)全部INFO
# 3. 大促期间日志量翻3-5倍

# MyBatis默认DEBUG,把每条SQL+参数都打出来
# HikariCP默认DEBUG,把连接池状态都打出来
# Spring Web默认INFO,把每次请求都打出来

正确配置(生产环境分级)

# application-prod.yml
logging:
  level:
    root: INFO  # 默认INFO
    com.example.business: INFO   # 业务代码
    org.springframework: WARN    # Spring框架
    org.mybatis: WARN            # MyBatis关掉
    com.zaxxer.hikari: WARN     # HikariCP关掉
    org.apache.tomcat: WARN      # Tomcat关掉
  file:
    name: /var/log/app/app.log
    max-size: 100MB              # 单文件100MB
    max-history: 7               # 保留7天
    total-size-cap: 10GB         # 总大小不超过10GB

生产环境:业务代码INFO、第三方库全部WARN或OFF。业务级INFO + 第三方WARN,日志量能从500MB/天降到50MB/天。

5

Profile激活:忘了指定?配置文件全乱套

事故场景:某团队启动命令没指定profile,Spring Boot默认加载application.yml,直接连到了测试库的数据库。测试数据被生产服务读出来,用户看到一堆测试账号,运营群里炸了。修复花了2小时,事故报告写了8页。

默认配置的问题

# 没有指定profile时,Spring Boot只加载 application.yml
# 而 application.yml 里通常写的是开发配置:

# application.yml(开发配置)
spring:
  datasource:
    url: jdbc:mysql://192.168.1.100:3306/test_db
    username: dev_user
    password: dev_pass
logging:
  level:
    com.example.business: DEBUG

正确配置(强制Profile)

# application.yml(公共配置)
spring:
  profiles:
    active: dev  # 开发默认dev
  application:
    name: my-service

# application-prod.yml(生产配置)
spring:
  datasource:
    url: jdbc:mysql://prod-db:3306/prod_db
    username: ${DB_USER}    # 从环境变量读
    password: ${DB_PASS}
logging:
  level:
    com.example.business: INFO
    org.springframework: WARN

生产环境启动时强制指定profile

# K8s deployment
env:
  - name: SPRING_PROFILES_ACTIVE
    value: "prod"  # 强制prod,dev/staging都不会生效

# 启动命令
java -jar -Dspring.profiles.active=prod app.jar

# 或者用环境变量
export SPRING_PROFILES_ACTIVE=prod
java -jar app.jar

经验:生产环境的启动命令必须显式指定profile,并且profile配置必须和默认配置严格区分。配置文件结构建议:application.yml(公共)+ application-{profile}.yml(环境特定),profile从环境变量读,不允许在代码里硬编码。

5项配置速查表

配置项

默认值(坑)

建议值

不配的后果

server.tomcat.threads.max

200

峰值QPS × 平均RT × 1.5

高并发排队超时

spring.datasource.hikari.maximum-pool-size

10

≤ DB max_connections × 30%

连接池排队,慢SQL

management.endpoints.web.exposure.include

health,info

health,info,metrics,prometheus

数据库密码泄漏

logging.level.root

INFO

INFO + 第三方库WARN

日志爆炸,磁盘写满

spring.profiles.active

default

从环境变量注入prod

配置错乱,测试库上线

这5项是Spring Boot上线前的最低必查项,不是"建议配置"。任何一项缺失,在生产环境高并发场景下都会直接暴露问题。配置项之间不冲突,可以一次性全部加上。

配置检查清单(打印出来贴工位)

□ Tomcat线程数按QPS估算(不小于500)
□ HikariCP连接池按DB能力估算(不小于20)
□ Actuator端点最小暴露(不包含env/heapdump)
□ 生产日志级别(业务INFO + 第三方WARN)
□ 启动命令显式指定prod profile
□ 配置文件分环境(application-{profile}.yml)
□ 敏感配置从环境变量读(不用明文密码)
□ 配置变更记录到Git(不直接在服务器改)

Spring Boot配置检查,飞算JavaAI帮你30秒扫完

这5项配置在Spring Boot项目里非常容易遗漏——特别是HikariCP连接池大小和Actuator端点暴露,靠人工Code Review经常漏掉。飞算JavaAI的代码审查器可以自动扫描项目中的application.yml、application.properties、logback.xml等配置文件,检查生产环境关键配置项是否合理,包括Tomcat线程数是否够用、HikariCP连接池是否合理、Actuator端点是否过度暴露、生产环境日志级别是否过高等。30秒跑完5项检查,给出具体的修复建议和示例配置。

你的Spring Boot项目里,这5项配置有几项是默认值的?

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐