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.

Reply via email to