java - keycloak spring boot starter 内存泄漏

标签 java spring spring-boot memory-leaks keycloak

我的后端微服务因生产环境中的 OutOfMemory 异常而崩溃。
/////////////////////////////////
更新:看起来问题来自嵌入式 tomcat,我发现了这个
enter image description here
它存储每个请求的 session 。目前不知道如何清洁它。我有这个配置:

server:
  port: 38083
  compression:
    enabled: true
    mime-types: text/html, text/xml, text/plain, text/css, application/javascript, application/json
    min-response-size: 1024


spring:
  session:
    store-type: none
    timeout: 1
////////////////////////
我仍然不确定,但看起来问题来自org.keycloak.representations.AccessToken.roles哈希映射。目前,我尽可能将微服务减少到最简单,我只有这个 Controller :
@RestController
@RequestMapping("/nurse")
public class NurseController {


  List<NurseDto> cache = null;

  public NurseController() {
    cache = new ArrayList<>();
    int i = 5000;
    while (i-- > 0) {
      NurseDto n = new NurseDto();
      n.setId("123");
      n.setInternalId("234234");
      n.setName("asdfasfasoinasdf");
      n.setType("NURSE");
      cache.add(n);
    }
  }


  @GetMapping
  public ResponseEntity<List<NurseDto>> findAllNurses() {
    return ResponseEntity.ok(cache);
  }
}
我从 20 个线程调用这个 Controller ,没有任何停顿。几分钟后,应用程序因内存泄漏异常而失败。同时,我从堆转储中获得了以下信息:
dump1
有了这个数量的对象:
dump2
其中 99% 的哈希映射节点指的是 org.keycloak.representations.AccessToken.roles
并且 99% 的字符串指的是访问 token 的权限。
以前,应用程序与
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-spring-boot-starter</artifactId>
    <version>6.0.1</version>
</dependency>
但在我将其更新到 11.0.2 后问题仍然存在
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-spring-boot-starter</artifactId>
    <version>11.0.2</version>
</dependency>
任何想法为什么会发生?这是理想的行为,我应该设置类似“缓存”限制的东西吗?
这是我的安全配置,可能有帮助:
@KeycloakConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Profile("!test")
public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

  @Autowired
  public void configure(AuthenticationManagerBuilder auth) {
    auth.authenticationProvider(keycloakAuthenticationProvider());
  }

  @Bean
  public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
    return new KeycloakSpringBootConfigResolver();
  }

  @Bean
  @Override
  protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
    return new NullAuthenticatedSessionStrategy();
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.authorizeRequests().anyRequest().permitAll().and().cors().and().csrf().disable();
  }

  @Bean
  public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.setAllowedOrigins(Collections.singletonList("*"));
    config.setAllowedHeaders(Collections.singletonList("*"));
    config.setAllowedMethods(
        Arrays.stream(HttpMethod.values()).map(HttpMethod::name).collect(Collectors.toList()));
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
  }
}

最佳答案

这是因为 tomcat session 。 Tomcat 为每个请求创建 session ,并将它们存储一个小时,在它可以清理内存之后。我找到了这个解决方案:

http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
例如,spring 安全配置应如下所示:
@KeycloakConfiguration
public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.authorizeRequests().anyRequest().permitAll().and().cors().and().csrf().disable();
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  }
  
常识告诉它应该是不够的,因为 session 是在 tomcat 容器级别创建的,我正在尝试使用 servlet 配置,它是在容器内部启动的,但它工作得很好。我也尝试设置 Spring 属性,如下所示:
  servlet:
    session:
      cookie:
        http-only: true
        secure: true
        max-age: 1
      timeout: 1s
结果是相似的,但当然它仍然会创建 1 秒的 session 。目前我不记得当我将超时设置为 0 时它的行为,但我停止了我的发现
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
没有任何其他 Spring 配置。

关于java - keycloak spring boot starter 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64501743/

相关文章:

java - 在 Spring Boot 应用程序中的其他一些 bean 之前创建/初始化一个 bean

java - 访问 spring bean 代理引用本身

java - 使用 Thymeleaf 渲染 HTML 模板时出错 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor'

java - 使用 Maven 构建的可执行 Jar 无法在运行时解决多个数据库驱动程序的依赖关系

java - 获取乘客名单并将他们安排到座位上。数组列表

java - 使用 java 获取正在运行的应用程序列表,然后向其发送按键

Spring Security 自定义身份验证失败处理程序重定向参数

java - 在构造函数或方法主体之外无法识别公共(public)静态变量

java - Spring Boot 电子邮件发送抛出 SocketTimeoutException : Read timed out

spring - 服务层中的 I18n