Spring Boot或Spring Security内存可能泄漏

迈克尔·考克森

我一直在通过浸泡测试运行带有Spring Security的Spring Boot应用程序,发现它逐渐填满了内存分配。

我使用以下命令启动了该应用程序:

java -Xmx128m -XX:+ PrintGCDetails -XX:+ PrintGCTimeStamps -Xloggc:gc.log -verbose:gc -jar target / myapp-0.0.1-SNAPSHOT.jar

这样我就可以获取gc信息,并限制内存更快地达到OutOfMemoryError的情况(半小时,而不是两周)

我已经使用tomcat和jetty作为容器来运行它,然后运行了一个bash脚本,该脚本在服务器上激发了很多cURL,以模拟生产中的负载。我将jmap指向该过程,并在崩溃前不久得到了以下信息(仅显示了前40个结果,并显示了tomcat的运行情况)

 num     #instances         #bytes  class name
----------------------------------------------
   1:        395984       32564344  [C
   2:        388697        9328728  java.lang.String
   3:         61258        5915088  [B
   4:        100297        4814256  java.util.HashMap
   5:         50892        4478496  org.apache.catalina.session.StandardSession
   6:         58774        3656824  [Ljava.util.HashMap$Node;
   7:         84773        3390920  java.util.TreeMap$Entry
   8:         51522        3339304  [Ljava.util.Hashtable$Entry;
   9:         51834        3317376  java.util.concurrent.ConcurrentHashMap
  10:        102111        3267552  java.util.HashMap$Node
  11:         96256        3080192  java.util.concurrent.ConcurrentHashMap$Node
  12:         24101        2754560  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  13:         51472        2470656  java.util.Hashtable
  14:         55102        2204080  java.util.LinkedHashMap$Entry
  15:         83020        1992480  java.util.ArrayList
  16:         34353        1923768  java.util.LinkedHashMap
  17:         59156        1892992  org.springframework.boot.loader.util.AsciiBytes
  18:         29574        1656144  org.springframework.boot.loader.jar.JarEntryData
  19:         18029        1586552  java.lang.reflect.Method
  20:         28391        1562080  [Ljava.lang.Object;
  21:         37178        1487120  java.lang.ref.SoftReference
  22:         47648        1446600  [I
  23:         52337        1256088  java.lang.Long
  24:         26134        1254432  java.util.TreeMap
  25:         50904        1221696  java.beans.PropertyChangeSupport
  26:         11777        1214464  java.lang.Class
  27:         23748        1139904  org.springframework.security.oauth2.provider.OAuth2Request
  28:         35994         863856  java.util.Collections$UnmodifiableRandomAccessList
  29:         50904         814464  java.beans.PropertyChangeSupport$PropertyChangeListenerMap
  30:         50892         814272  org.apache.catalina.session.StandardSessionFacade
  31:         49748         795968  java.util.HashSet
  32:         24066         770112  java.util.Collections$UnmodifiableMap
  33:         23748         759936  org.springframework.security.oauth2.provider.OAuth2Authentication
  34:         23748         759936  org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails
  35:         26000         624000  javax.management.openmbean.CompositeDataSupport
  36:         12015         576664  [Ljava.lang.String;
  37:         16319         522208  com.sun.org.apache.xerces.internal.xni.QName
  38:         15288         489216  java.lang.ref.WeakReference
  39:         26448         423168  java.util.LinkedHashSet
  40:         26011         416176  java.util.TreeMap$KeySet

如您所见,有许多正在运行的tomcat StandardSessions堆,还有许多OAuth2Authentication实例(远远超过我预期的2或3个实例)。在发生OutOfMemoryError之前,这两种方法的数量一直在增长。都没有被收集。

我实现了下面提供的spring安全配置

@Configuration
@ComponentScan("com.xxx.xxxxx")
public class TokenConfig {

    private static final String RESOURCE_ID = "touchAuth";

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(ResourceServerConfiguration.class);

        @Autowired
        TouchUserDetailsService touchUserDetailsService;

        @Autowired
        TouchUserAuthenticationFilter touchUserAuthenticationFilter;

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            resources
                    .resourceId(RESOURCE_ID);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {


            //@formatter: off

            http
                    .addFilterBefore(touchUserAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                    .requestMatchers()
                        .antMatchers("/**/secure/**", "/basket/**", "/transactions/**", "/support-requests/**", "/devices/resources/**", "/devices/information/**", "/devices/support-request", "/retailers/resources/**", "/news-items-display/last")
                    .and()
                    .authorizeRequests()
                        .anyRequest()
                        .authenticated();


            //@formatter: on
        }


    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends
            AuthorizationServerConfigurerAdapter {

        @Autowired
        DataSource dataSource;

        @Autowired
        private JdbcTokenStore jdbcTokenStore;

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints)
                throws Exception {
            endpoints
                    .tokenStore(jdbcTokenStore);
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients
                    .jdbc(dataSource);

        }

    }

    @Configuration
    @EnableWebSecurity
    protected static class SecurityConfig extends WebSecurityConfigurerAdapter{


        @Autowired
        private TxxxxxUserDetailsService txxxxxUserDetailsService;

        @Autowired
        DataSource dataSource;


        @Bean
        public JdbcTokenStore jdbcTokenStore() {
            JdbcTokenStore jdbcTokenStore = new JdbcTokenStore(dataSource);

            return jdbcTokenStore;
        }

        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {

            DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();

            authenticationProvider.setUserDetailsService(touchUserDetailsService);
            List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
            authenticationProviders.add(authenticationProvider);


            ProviderManager providerManager = new ProviderManager(authenticationProviders);
            return providerManager;
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .headers().disable()  // allow things to be displayed in iframes, for example.
                    .csrf().disable()
                    .authorizeRequests()
                    .antMatchers("/favicon.ico").permitAll()
                    .antMatchers("/css/*").permitAll()
                    .antMatchers("/images/*").permitAll()
                    .antMatchers("/error*").permitAll()
                    .antMatchers("/ping").permitAll()
                    .antMatchers("/info").permitAll()
                    .antMatchers("/").permitAll()
                    .antMatchers("/content/**").permitAll()
                    .antMatchers("/devices/commission").permitAll()
                    .antMatchers("/devices/device-import").permitAll()
                    .antMatchers("/devices/list").permitAll()
                    .antMatchers("/devices/modify").permitAll()
                    .antMatchers("/news-items-management/**").permitAll()
                    .antMatchers("/news-items-display/*").permitAll()
                    .antMatchers("/support-request-management/*").permitAll()
                    .anyRequest()
                    .authenticated();
        }
    }
}

我也有过滤器,也在下面提供

@Component
public class TxxxxUserAuthenticationFilter
        extends AbstractAuthenticationProcessingFilter {

    private static final Logger LOG = LoggerFactory.getLogger(TxxxxUserAuthenticationFilter.class);

    public static final String FILTER_PROCESS_URL = "/login";

    public static final String X_STANDALONE = "X_STANDALONE";
    public static final String YES = "YES";

    protected TxxxxUserAuthenticationFilter() {
        super(FILTER_PROCESS_URL);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {

        LOG.debug("attemptAuthentication invoked");
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if (username == null) {
            username = "";
        }

        if (password == null) {
            password = "";
        }

        username = username.trim();

        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
        Authentication authentication = this.getAuthenticationManager().authenticate(authRequest);

        request.getSession().setAttribute("SESSION_AUTHENTICATED", authentication);

        return authentication;
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {


        HttpServletRequest httpServletRequest = (HttpServletRequest) req;
        SecurityContext securityContext = (SecurityContext) httpServletRequest.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
        if (isLoginRequest(httpServletRequest)) {
            super.doFilter(req, res, chain);
            return;
        }

        // If the Authorization header is absent, the framework treats it as a non-oauth request and continues the security chain.
        if (securityContext != null && ((HttpServletRequest) req).getHeader("Authorization") == null) {
            securityContext.setAuthentication(null);
        }

        // Throw an exception if standalone device and a valid authentication is not found.
        if (requiresFormAuthentication(httpServletRequest) ) {

            Authentication authentication = (Authentication)httpServletRequest.getSession().getAttribute("SESSION_AUTHENTICATED");
            if(authentication == null || !authentication.isAuthenticated()) {
                throw new AuthenticationCredentialsNotFoundException("Access denied");
            }
        }

        chain.doFilter(req, res);

    }



    private boolean doesAuthExistsInContext(SecurityContext securityContext) {
        return securityContext != null && securityContext.getAuthentication() != null;
    }

    private boolean requiresFormAuthentication(HttpServletRequest httpServletRequest) {

        return  YES.equalsIgnoreCase(httpServletRequest.getHeader(X_STANDALONE));
    }

    private boolean isLoginRequest(HttpServletRequest req) {
        return FILTER_PROCESS_URL.equalsIgnoreCase(req.getRequestURI());
    }

    @Autowired
    public void setAuthenticationManagerBean (AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }

}

有谁知道内存泄漏的根源是什么?为什么我要打开这么多的Tomcat(或Jetty)会话?

显然,这里的房间有限,但是如果需要任何其他信息,我很乐意为您服务。

谢谢

迭戈·马加良斯

您在这里和我们一样。看看@ https://github.com/spring-projects/spring-boot/issues/2084

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用Spring Boot配置Spring Security

来自分类Dev

how to implement a authentication with spring boot security?

来自分类Dev

Spring Boot内存利用率

来自分类Dev

由于Spring单例导致内存泄漏

来自分类Dev

Spring Boot中Spring Security的XML配置

来自分类Dev

Spring Boot / Spring Security正在忽略来自JavaScript的/ login调用

来自分类Dev

Spring Boot或Spring Security内存可能泄漏

来自分类Dev

Spring Boot + Spring MVC + Ratpack是否可能?

来自分类Dev

使用AspectJ的Spring Boot + Spring Security无法正常工作

来自分类Dev

Spring Boot ServeletInitializer和Spring Security

来自分类Dev

spring-boot,spring-security和dropwizard指标

来自分类Dev

如何在Spring Boot中覆盖Spring Security默认配置

来自分类Dev

Spring Boot Security + Thymeleaf:缺少IProcessorDialect类

来自分类Dev

Spring Security / Spring Boot-如何为用户设置ROLES

来自分类Dev

Spring Boot Security 403重定向

来自分类Dev

Spring Boot的默认内存设置是什么?

来自分类Dev

从Spring Boot Oauth2迁移到Spring Security 5

来自分类Dev

Spring Boot-内存泄漏-H2数据库-不注销驱动程序

来自分类Dev

没有Spring Security的Spring-Boot登录

来自分类Dev

从Spring Boot连接到内存中的ElasticSearch

来自分类Dev

Spring Boot-如何终止当前的Spring Security会话?

来自分类Dev

Spring Boot元空间内存泄漏

来自分类Dev

带有Spring Boot的Spring Security

来自分类Dev

Spring Boot + Security + JWT 无法生成token

来自分类Dev

如何使用 Spring Security 在 Spring Boot 中管理会话?

来自分类Dev

Spring Boot 在 AWS 上的 Docker 中登录到系统输出是否存在内存泄漏?

来自分类Dev

Spring Boot、Spring Security - 防止 MongoDB 的直接 URL 查询

来自分类Dev

内存中的spring boot activemq

来自分类Dev

Spring boot DelegatingSecurityContextAsyncTaskExecutor 导致潜在的内存泄漏

Related 相关文章

  1. 1

    使用Spring Boot配置Spring Security

  2. 2

    how to implement a authentication with spring boot security?

  3. 3

    Spring Boot内存利用率

  4. 4

    由于Spring单例导致内存泄漏

  5. 5

    Spring Boot中Spring Security的XML配置

  6. 6

    Spring Boot / Spring Security正在忽略来自JavaScript的/ login调用

  7. 7

    Spring Boot或Spring Security内存可能泄漏

  8. 8

    Spring Boot + Spring MVC + Ratpack是否可能?

  9. 9

    使用AspectJ的Spring Boot + Spring Security无法正常工作

  10. 10

    Spring Boot ServeletInitializer和Spring Security

  11. 11

    spring-boot,spring-security和dropwizard指标

  12. 12

    如何在Spring Boot中覆盖Spring Security默认配置

  13. 13

    Spring Boot Security + Thymeleaf:缺少IProcessorDialect类

  14. 14

    Spring Security / Spring Boot-如何为用户设置ROLES

  15. 15

    Spring Boot Security 403重定向

  16. 16

    Spring Boot的默认内存设置是什么?

  17. 17

    从Spring Boot Oauth2迁移到Spring Security 5

  18. 18

    Spring Boot-内存泄漏-H2数据库-不注销驱动程序

  19. 19

    没有Spring Security的Spring-Boot登录

  20. 20

    从Spring Boot连接到内存中的ElasticSearch

  21. 21

    Spring Boot-如何终止当前的Spring Security会话?

  22. 22

    Spring Boot元空间内存泄漏

  23. 23

    带有Spring Boot的Spring Security

  24. 24

    Spring Boot + Security + JWT 无法生成token

  25. 25

    如何使用 Spring Security 在 Spring Boot 中管理会话?

  26. 26

    Spring Boot 在 AWS 上的 Docker 中登录到系统输出是否存在内存泄漏?

  27. 27

    Spring Boot、Spring Security - 防止 MongoDB 的直接 URL 查询

  28. 28

    内存中的spring boot activemq

  29. 29

    Spring boot DelegatingSecurityContextAsyncTaskExecutor 导致潜在的内存泄漏

热门标签

归档