Search code examples
javaspringspring-bootloadsession-management

Limit the total amount of sessions in a Sprint Boot application


In our Spring Boot web server, I know how to limit the sessions per user (httpSecurity.sessionManagement().maximumSessions()), but I want to limit the total amount of sessions, to avoid load on the server.

How can this be done?


Solution

  • If 'total number of users' is a meaningful proxy for 'load' (see the comment from @JBNizet) in your system e.g. if most requests are ~identical in terms of resource footprint then you could define your own implementation of SessionAuthenticationStrategy. Here's a simple example:

    private class AllUsersConcurrentSessionControlAuthenticationStrategy extends ConcurrentSessionControlAuthenticationStrategy {
    
        // probably inject this from application configuration
        private final int maxUsers;
        private final SessionRegistry sessionRegistry;
    
        public AllUsersConcurrentSessionControlAuthenticationStrategy(int maxUsers, SessionRegistry sessionRegistry) {
            super(sessionRegistry);
            this.maxUsers = maxUsers;
            this.sessionRegistry = sessionRegistry;
        }
    
        @Override
        public void onAuthentication(Authentication authentication, HttpServletRequest request,
                                     HttpServletResponse response) {
            if (sessionRegistry.getAllPrincipals().size() > maxUsers) {
                throw new SessionAuthenticationException("...");
            }
            super.onAuthentication(authentication, request, response);
        }
    }
    

    You register this like so:

    http.sessionManagement().sessionAuthenticationStrategy(new AllUsersConcurrentSessionControlAuthenticationStrategy(maxUsers, sessionRegistry));
    

    However, if 'total number of users' is not a meaningful proxy for 'load' then you should perhaps consider implementing your services in a non-blocking manner with each endpoint passing its request off to a threadpool and the request-to-threadpool allocation strategy could take into account how 'heavy' the request is. Lightweight requests could be handled by a large threadpool, heavyweitgh requests could be handled by a smaller threadpool.