spring-session icon indicating copy to clipboard operation
spring-session copied to clipboard

memory leak when session save model is "always"

Open gabrielsky opened this issue 4 years ago • 3 comments

Describe the bug version:2.4.3 when a user after logging in , RedisIndexedSessionRepository will add sessionid to redis key: "sessionAttr:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME" type of set, the question is if you set save-mode to always, the sessionId will never be remove from this set after you call request.invalidate()

spring.session.redis.save-mode=always

To Reproduce

  1. config
spring.session.redis.save-mode=always
  1. login any user:test, just create sessionId
  2. logout user:test,call request.invalidate()
  3. look data in redis ,the sessionId still in "sessionAttr:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:test"

Expected behavior when call request.invalidate() redis remove sessionid from redis set :"sessionAttr:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:test"

** other ** after set spring.session.redis.save-mode=always in Reproduce3 put all attributes to this.delta every RedisSession instance

if (this.isNew || (RedisIndexedSessionRepository.this.saveMode == SaveMode.ALWAYS)) {
				getAttributeNames().forEach((attributeName) -> this.delta.put(getSessionAttrNameKey(attributeName),
						cached.getAttribute(attributeName)));
			}

then clean sessionId from redis set

	private void cleanupPrincipalIndex(RedisSession session) {
		String sessionId = session.getId();
		Map<String, String> indexes = RedisIndexedSessionRepository.this.indexResolver.resolveIndexesFor(session);
		String principal = indexes.get(PRINCIPAL_NAME_INDEX_NAME);
		if (principal != null) {
			this.sessionRedisOperations.boundSetOps(getPrincipalKey(principal)).remove(sessionId);
		}
	}

but at last call saveDelta() re add sessionId

private void saveDelta() {
	if (this.delta.isEmpty()) {
		return;
	}
	String sessionId = getId();
	getSessionBoundHashOperations(sessionId).putAll(this.delta);
	String principalSessionKey = getSessionAttrNameKey(
			FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
	String securityPrincipalSessionKey = getSessionAttrNameKey(SPRING_SECURITY_CONTEXT);
	if (this.delta.containsKey(principalSessionKey) || this.delta.containsKey(securityPrincipalSessionKey)) {
		if (this.originalPrincipalName != null) {
			String originalPrincipalRedisKey = getPrincipalKey(this.originalPrincipalName);
			RedisIndexedSessionRepository.this.sessionRedisOperations.boundSetOps(originalPrincipalRedisKey)
					.remove(sessionId);
		}
		Map<String, String> indexes = RedisIndexedSessionRepository.this.indexResolver.resolveIndexesFor(this);
		String principal = indexes.get(PRINCIPAL_NAME_INDEX_NAME);
		this.originalPrincipalName = principal;
		if (principal != null) {
			String principalRedisKey = getPrincipalKey(principal);
			RedisIndexedSessionRepository.this.sessionRedisOperations.boundSetOps(principalRedisKey)
					.add(sessionId);
		}
	}

	this.delta = new HashMap<>(this.delta.size());

	Long originalExpiration = (this.originalLastAccessTime != null)
			? this.originalLastAccessTime.plus(getMaxInactiveInterval()).toEpochMilli() : null;
	RedisIndexedSessionRepository.this.expirationPolicy.onExpirationUpdated(originalExpiration, this);
}

Please help to check whether there is this problem

gabrielsky avatar Apr 21 '21 08:04 gabrielsky

Apologies for the non-related post, but can you point to a sample using 1. reactive websockets + 2. session

phnxfire avatar May 11 '21 03:05 phnxfire

spring.session.redis.save-mode=always

This will cause the memory used of redis server keep growing when session create day by day , but can't be removed after request.invalidate() the memory leak redis key is like :"sessionAttr:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:test"

Apologies for the non-related post, but can you point to a sample using 1. reactive websockets + 2. session

gabrielsky avatar Jun 19 '21 04:06 gabrielsky

Not only the always mode, but also the on-save mode has the same problem. All sessions under the key "sessionAttr:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:" will never be deleted unless logout is explicitly called.

baozi-2019 avatar Apr 14 '23 02:04 baozi-2019