Graylog2 / Graylog2/graylog2-server

Shiro Session CacheManger is not meant for distrubed usage

Open
#15,185 0 comments 0 reactions 0 assignees View on GitHub
bug performance triaged
Dominant language
Java
Stars
8.1k
Forks
1.1k
Avg merge
1d 20h
Merged PRs (30d)
217

Description

Graylog is using the `MemoryConstrainedCacheManager`
https://github.com/Graylog2/graylog2-server/blob/master/graylog2-server/src/main/java/org/graylog2/bindings/providers/DefaultSecurityManagerProvider.java#L88

Which is not meant to be used for a Graylog cluster:
https://shiro.apache.org/caching.html

> The [MemoryConstrainedCacheManager](https://shiro.apache.org/static/current/apidocs/org/apache/shiro/cache/MemoryConstrainedCacheManager.html) is a CacheManager implementation suitable for single-JVM production environments. It is not clustered/distributed, so if your application spans across more than one JVM (e.g. web app running on multiple web servers), and you want cache entries to be accessible across JVMs, you will need to use a distributed cache implement instead.

In a Graylog cluster, we can end up in a situation where a node receives requests for sessions
that are not in the nodes in-memory cache, and will not be stored there either.

This is due to the fact that the cache is only populated when the session is created or updated.
Requests that don't update the session (`X-Graylog-No-Session-Extension: true`)
will never add the session to the cache.

Not having the session the cache is very inefficient and requires up to 10 mongoDB lookups for the non-exisinting session
per request.

## Possible Solution

A simple workaround could be to update the session cache after every read:

```java
--- graylog2-server/src/main/java/org/graylog2/security/MongoDbSessionDAO.java
+++ graylog2-server/src/main/java/org/graylog2/security/MongoDbSessionDAO.java
@@ -78,7 +78,12 @@ public class MongoDbSessionDAO extends CachingSessionDAO {
// expired session or it was never there to begin with
return null;
}
- return getSimpleSession(sessionId, dbSession);
+ final SimpleSession simpleSession = getSimpleSession(sessionId, dbSession);
+ // If the session was created on a different cluster node, we need to cache it here as well.
+ // Caching only happens for CachingSessionDAO.create() and CachingSessionDAO.update()
+
+ cache(simpleSession, sessionId);
+ return simpleSession;
}

```

But maybe we should investigate the possibility of using a distributed cachemanager...

* Graylog Version: 5.1.0-SNAPSHOT (but that code is ancient)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.