Hello, we use CAS 7.0.0 with Redis, and we also have memory leak. Anyone have a solutions?
Thanks and Best regards. wtorek, 4 czerwca 2024 o 16:46:26 UTC+2 Nathan Cailbourdin napisał(a): > Hello, > > Since version 7 of CAS, I have noticed an abnormal and progressive > increase in the memory consumed by the metaspace when the Redis ticket > registry is used. This issue is due to accessor classes that are > dynamically generated by Spring Data to access the attributes of > RedisTicketDocument. > > The increase can easily be observed by monitoring the evolution of the > metaspace as soon as connections are made: https://postimg.cc/21p7znzd > Here, the example involves approximately 2000 users connecting to CAS, > using it to obtain STs, and then disconnecting. We can see the increase in > memory consumption during the connection phase (from 10:52 AM to 11:02 AM), > and especially, we do not observe any memory release even during the > disconnection phase (starting at 11:02 AM). > > In comparison, with the same number of connections but with the default > ticket registry, no metaspace increase is observed: > https://postimg.cc/zL8wh5HV > With CAS version 6 and the Redis ticket registry, we do not observe any > increase, so the problem only appears starting from version *7*. > > We can observe the class loading by launching the CAS server with the > argument *-Xlog:class+load=info*. The following message is displayed > during each new connection to CAS (with a different class name each time): > [info][class,load] org.apereo.cas.ticket.registry.RedisTicketDocument_ > *Accessor_ss8dk8* source: __JVM_LookupDefineClass__ > > If we look at the loaded classes with the command *jcmd PID VM.classes | > grep org.apereo.cas.ticket.registry.RedisTicketDocument_Accessor*, we can > see that for each new connection, a new accessor class is created: > 0x00007f03c1e0f218 73 fully_initialized W > org.apereo.cas.ticket.registry.RedisTicketDocument_*Accessor_ss8dk8* > 0x00007f03c1cbdab8 73 fully_initialized W > org.apereo.cas.ticket.registry.RedisTicketDocument_*Accessor_3aa8i2* > and the list goes on... > > > Debugging step by step, I found that the problem comes from > RedisTicketRegistry.java, specifically from the addOrUpdateTicket method: > https://github.com/apereo/cas/blob/v7.0.4/support/cas-server-support-redis-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/RedisTicketRegistry.java#L417 > > Tracing the call chain progressively, I found that the following method in > Spring Data is invoked: > https://github.com/spring-projects/spring-data-commons/blob/main/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java#L97 > > This call results in creating a new class (not a new instance, a new > class) because the PersistentPropertyAccessorFactory responsible for > creating accessor classes associated with the mapping context does not know > that a class has already been generated for this purpose. > A map (propertyAccessorClasses) is used to save the class type (here > RedisTicketDocument) to its associated accessor class, but in our case, it > becomes empty for each new ticket! (Whereas it should only be empty for the > first one, see > https://github.com/spring-projects/spring-data-commons/blob/main/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java#L186 > ) > > This issue is due to a new RedisKeyValueAdapter being created for each > call to addOrUpdateTicket, resulting in a new RedisMappingContext being > created each time. *When a new RedisMappingContext is created, it also > creates a new PersistentPropertyAccessorFactory, which does not have > knowledge of the previously created accessor class and will create a new > one when it tries to access the ticket attributes.* > > RedisMappingContext instances are created in this method: > https://github.com/apereo/cas/blob/v7.0.4/support/cas-server-support-redis-ticket-registry/src/main/java/org/apereo/cas/ticket/registry/RedisTicketRegistry.java#L439 > > > They seem to depend on a KeyspaceConfiguration that changes based on the > TGT. We cannot directly modify the MappingConfiguration or > KeyspaceConfiguration as they are final attributes (which explains why a > new MappingConfiguration is recreated each time). > > *My question is: what would be the best way to solve this problem?* > > > A potential fix would be to create only one RedisMappingContext, then > dynamically change its KeyspaceSettings in the buildRedisKeyValueAdapter > method. In other words, this would involve this change in the > buildRedisKeyValueAdapter method: > > *this.redisMappingContext.getMappingConfiguration().getKeyspaceConfiguration().addKeyspaceSettings(new > > KeyspaceConfiguration.KeyspaceSettings(RedisTicketDocument.class, > redisKeyPattern)); val adapter = new > RedisKeyValueAdapter(casRedisTemplates.getTicketsRedisTemplate(), > this.redisMappingContext) * > > With this modification, the metaspace memory consumption returns to > normal, but maybe there is a better way to solve the problem. > > > Thanks in advance for your assistance. > Best regards. -- - Website: https://apereo.github.io/cas - List Guidelines: https://goo.gl/1VRrw7 - Contributions: https://goo.gl/mh7qDG --- You received this message because you are subscribed to the Google Groups "CAS Community" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/a/apereo.org/d/msgid/cas-user/4c7c2843-39a5-431c-8a97-2d8160bf7f26n%40apereo.org.
