ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot启动慢得像蜗牛?原来是这个配置在捣鬼

SpringBoot启动慢得像蜗牛?原来是这个配置在捣鬼 上周三凌晨我们的订单服务在预发环境启动耗时突然从15秒飙升到2分钟——而代码和依赖压根没改这种诡异的性能劣化就像代码里藏了一只蜗牛逼得我不得不翻开SpringBoot的黑匣子。一、症状启动时间为何突然暴涨现象很简单同样的代码在本地开发环境启动飞快但在预发环境K8sJVM 11却慢得离谱。盯着启动日志看了半小时终于发现一个可疑的片段2023-xx-xx 02:15:23.123 INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean configurationPropertiesBeanFactoryPostProcessor of type [org.springframework.boot.context.properties.ConfigurationPropertiesBeanFactoryPostProcessor] is not eligible for getting processed by all BeanPostProcessors 2023-xx-xx 02:16:51.456 INFO o.s.b.w.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)注意两个日志的时间戳——BeanPostProcessor检查阶段竟然卡了88秒这显然不是正常的IOC容器初始化耗时。二、根因ConfigurationProperties的扫描地狱通过Arthas的trace命令跟踪Bean加载过程发现罪魁祸首是一个不起眼的配置# 错误的配置方式 spring: config: import: classpath:application-common.yml profiles: active: profileActive问题出在profileActive这个占位符。SpringBoot在解析ConfigurationProperties时会递归扫描所有可能影响属性值的元数据而 Maven/Gradle 的资源过滤Resource Filtering会在编译期将占位符替换为实际值。但在某些条件下比如CI环境中未正确配置过滤占位符未被替换导致SpringBoot试图解析profileActive时触发ConfigurationPropertySourcesPropertyResolver的深度递归由于未找到匹配的配置源每次解析都会重新扫描classpath下的所有META-INF/spring-configuration-metadata.json文件项目中引入了30个三方库每个库都有自己的metadata扫描成本指数级上升三、解法停止滥用占位符正确的做法是严格区分编译期占位符和运行期占位符。对于profile这种启动时就必须确定的属性改用以下方式!-- pom.xml -- profiles profile idprod/id activation activeByDefaulttrue/activeByDefault /activation properties profileActiveprod/profileActive /properties /profile /profiles# application.yml spring: profiles: active: ${profileActive} # 这里必须是普通的Spring占位符关键差异var是Maven资源过滤语法编译期生效${var}是Spring占位符语法运行期解析四、性能对比在模拟环境中对比两种配置方式的启动耗时基于SpringBoot 2.7 50个依赖JAR配置方式启动时间元数据扫描次数profileActive118s240${profileActive}14s1五、避坑指南警惕组合配置spring.config.import 占位符极易引发元数据风暴慎用资源过滤.properties文件用var尚可但YAML的复杂结构容易解析异常检查三方库某些库如Spring Cloud Config会动态生成ConfigurationProperties加剧扫描负担日志监控遇到启动慢时先检查BeanPostProcessorChecker阶段的耗时结语SpringBoot的便利性背后藏着太多隐形的性能陷阱。记住任何需要编译期解析的配置都不该出现在运行时的配置树上。你在项目中还遇到过哪些奇葩的启动性能问题评论区聊聊你的捉蜗牛经历。
返回列表