Spring Boot 3启用Basic Auth后CPU占用过高问题求助
问题描述
我有一个基于Spring Boot 3构建的Java应用,安全配置代码如下:
@Configuration @EnableWebSecurity @EnableMethodSecurity public class SecurityConfig { private static final String[] permitMethods = new String[]{ "/api/games/**", "/swagger-ui/**", "/v3/api-docs/**", "/actuator/**" }; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeRequests(authorizeRequests -> authorizeRequests .requestMatchers(permitMethods).permitAll() .anyRequest().authenticated() ) .userDetailsService(userDetailsService()) .httpBasic(Customizer.withDefaults()); return http.build(); } @Bean public UserDetailsService userDetailsService() { UserDetails user = User.withDefaultPasswordEncoder() .username("admin") .password("admin") .build(); return new CachingUserDetailsService(new InMemoryUserDetailsManager(user)); } }
执行压测时,仅用40个并行线程,应用CPU占用率就超过70%,线程数越多CPU占用越高。但移除.httpBasic(Customizer.withDefaults());配置后,CPU占用率直接降至10%。当前使用Spring Boot 3.1.1版本,尝试过3.0.0版本,结果一致。需要在保留Basic Auth的前提下降低CPU占用。
优化方案
1. 替换默认密码编码器
User.withDefaultPasswordEncoder()默认使用的BCryptPasswordEncoder是高开销的哈希算法,设计目的是抵御暴力破解,但高并发场景下会大量消耗CPU。可以根据场景替换为更高效的编码器:
- 测试环境:使用
NoOpPasswordEncoder(明文校验,仅用于测试) - 生产环境:使用
Argon2PasswordEncoder(安全性高且性能优于BCrypt)
示例代码:
@Bean public PasswordEncoder passwordEncoder() { // 生产环境推荐Argon2 return new Argon2PasswordEncoder(); // 测试环境可使用NoOp // return NoOpPasswordEncoder.getInstance(); } @Bean public UserDetailsService userDetailsService() { UserDetails user = User.builder() .username("admin") .password(passwordEncoder().encode("admin")) .build(); return new CachingUserDetailsService(new InMemoryUserDetailsManager(user)); }
2. 开启认证结果缓存
默认HTTP Basic不会缓存认证结果,每个请求都要重复解析Authorization头并校验用户信息。通过配置SecurityContextRepository实现认证结果缓存,减少重复校验开销:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeRequests(authorizeRequests -> authorizeRequests .requestMatchers(permitMethods).permitAll() .anyRequest().authenticated() ) .userDetailsService(userDetailsService()) .httpBasic(Customizer.withDefaults()) // 启用SecurityContext缓存,复用认证结果 .securityContext(securityContext -> securityContext .securityContextRepository(new DelegatingSecurityContextRepository( new RequestAttributeSecurityContextRepository(), new HttpSessionSecurityContextRepository() ))); return http.build(); }
3. 校验公开路径匹配规则
确保permitMethods中的路径配置准确,避免公开API或静态资源触发不必要的Basic Auth解析逻辑。可以通过调试确认请求是否被正确匹配到permitAll规则,减少无效的认证流程。
4. 调整容器线程池配置
Spring Boot默认Tomcat线程池在高并发下可能出现线程频繁创建销毁的情况,增加CPU开销。在application.properties中调整线程池参数:
# 调整Tomcat线程池配置 server.tomcat.threads.max=200 server.tomcat.threads.min-spare=50 server.tomcat.accept-count=100
内容的提问来源于stack exchange,提问作者Gog1nA
相关产品推荐
相关产品推荐

