简体   繁体   English

Spring Session 的推荐 Infinispan 缓存模式

[英]Recommended Infinispan cache mode for Spring Session

My app uses Infinispan's Spring Session implementation via the Infinispan Spring Boot Starter .我的应用通过Infinispan Spring Boot Starter使用 Infinispan 的 Spring Session 实现。 I am using the embedded mode via InfinispanEmbeddedHttpSessionConfiguration .我通过InfinispanEmbeddedHttpSessionConfiguration使用嵌入模式。 The Spring Session integration documentation is pretty sparse, and it doesn't mention anything about the recommended cache mode for the session cache. Spring Session 集成文档非常稀少,它没有提及 session 缓存的推荐缓存模式。

I have been using the DIST_SYNC mode, but I notice occasional ConcurrentModificationException errors in the log.我一直在使用 DIST_SYNC 模式,但我注意到日志中偶尔会出现ConcurrentModificationException错误。 Is there a more appropriate cache mode, or could this be a bug?是否有更合适的缓存模式,或者这可能是一个错误?

I am using Spring Boot 2.2.10, Infinispan 9.4.20 and Spring Session 2.2.0.我正在使用 Spring Boot 2.2.10、Infinispan 9.4.20 和 Spring Session 2.2.0。 The app runs under JDK 11.该应用程序在 JDK 11 下运行。

Edit编辑

The exception I observe in the logs is below.我在日志中观察到的异常如下。 I've put xxx.我放了xxx. in place of my company's package names for our filters.代替我公司过滤器的 package 名称。

The exception occurs when the same session is reused in quick succession, in particular when our external security vendor runs weekly scans on our app.当相同的 session 被快速连续重用时,会发生异常,特别是当我们的外部安全供应商每周对我们的应用程序进行扫描时。 The exception does not occur every week.并非每周都会发生异常。 When it does occur, it leads to an eventual OutOfMemory error on the node that did not get the ConcurrentModificationException .当它发生时,它最终会导致节点上没有获得ConcurrentModificationException的 OutOfMemory 错误。 The heap is full of TrianglePerCacheInboundInvocationHander$1 objects.堆中充满了TrianglePerCacheInboundInvocationHander$1对象。

I have tried to reproduce the error in our development environment by running concurrent requests for 3 days, but to no avail.我试图通过运行并发请求 3 天来重现我们的开发环境中的错误,但无济于事。

I've looked at the Infinispan Spring Session code, and I see that each request gets its own instance of MapSession , materialised from the serialised data stored in Infinispan.我查看了 Infinispan Spring Session 代码,我看到每个请求都有自己的MapSession实例,从存储在 Infinispan 中的序列化数据实现。 I don't see how multiple concurrent requests for the same session could cause the ConcurrentModificationException , and I'm not aware of anywhere in my app that would allow concurrent access to a MapSession instance from multiple threads.我看不到对同一个 session 的多个并发请求如何导致ConcurrentModificationException ,而且我不知道我的应用程序中允许从多个线程并发访问MapSession实例的任何地方。

04:46:25.758 ERROR o.i.r.r.RpcManagerImpl          - ISPN000073: Unexpected error while replicating
java.util.ConcurrentModificationException: null
    at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
    at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1526)
    at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1524)
    at org.infinispan.commons.marshall.MarshallUtil.marshallMap(MarshallUtil.java:52)
    at org.infinispan.marshall.exts.MapExternalizer.writeObject(MapExternalizer.java:63)
    at org.infinispan.marshall.exts.MapExternalizer.writeObject(MapExternalizer.java:31)
    at org.infinispan.marshall.core.GlobalMarshaller.writeInternal(GlobalMarshaller.java:638)
    at org.infinispan.marshall.core.GlobalMarshaller.writeInternalClean(GlobalMarshaller.java:643)
    at org.infinispan.marshall.core.GlobalMarshaller.lambda$findWriter$0(GlobalMarshaller.java:369)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:137)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
    at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)
    at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)
    at org.infinispan.marshall.core.ExternalJBossMarshaller.objectToObjectStream(ExternalJBossMarshaller.java:36)
    at org.infinispan.marshall.core.GlobalMarshaller.writeRawUnknown(GlobalMarshaller.java:617)
    at org.infinispan.marshall.core.GlobalMarshaller.writeUnknown(GlobalMarshaller.java:612)
    at org.infinispan.marshall.core.GlobalMarshaller.writeNonNullableObject(GlobalMarshaller.java:412)
    at org.infinispan.marshall.core.GlobalMarshaller.writeNullableObject(GlobalMarshaller.java:355)
    at org.infinispan.marshall.core.BytesObjectOutput.writeObject(BytesObjectOutput.java:26)
    at org.infinispan.commands.triangle.SingleKeyBackupWriteCommand.writeTo(SingleKeyBackupWriteCommand.java:125)
    at org.infinispan.marshall.exts.ReplicableCommandExternalizer.writeCommandParameters(ReplicableCommandExternalizer.java:71)
    at org.infinispan.marshall.exts.CacheRpcCommandExternalizer.marshallParameters(CacheRpcCommandExternalizer.java:118)
    at org.infinispan.marshall.exts.CacheRpcCommandExternalizer.writeObject(CacheRpcCommandExternalizer.java:114)
    at org.infinispan.marshall.exts.CacheRpcCommandExternalizer.writeObject(CacheRpcCommandExternalizer.java:65)
    at org.infinispan.marshall.core.GlobalMarshaller.writeInternal(GlobalMarshaller.java:638)
    at org.infinispan.marshall.core.GlobalMarshaller.writeNonNullableObject(GlobalMarshaller.java:402)
    at org.infinispan.marshall.core.GlobalMarshaller.writeNullableObject(GlobalMarshaller.java:355)
    at org.infinispan.marshall.core.GlobalMarshaller.writeObjectOutput(GlobalMarshaller.java:183)
    at org.infinispan.marshall.core.GlobalMarshaller.writeObjectOutput(GlobalMarshaller.java:176)
    at org.infinispan.marshall.core.GlobalMarshaller.objectToBuffer(GlobalMarshaller.java:305)
    at org.infinispan.remoting.transport.jgroups.JGroupsTransport.marshallRequest(JGroupsTransport.java:1031)
    at org.infinispan.remoting.transport.jgroups.JGroupsTransport.sendCommand(JGroupsTransport.java:1217)
    at org.infinispan.remoting.transport.jgroups.JGroupsTransport.sendToMany(JGroupsTransport.java:276)
    at org.infinispan.remoting.rpc.RpcManagerImpl.sendToMany(RpcManagerImpl.java:390)
    at org.infinispan.interceptors.distribution.TriangleDistributionInterceptor.sendToBackups(TriangleDistributionInterceptor.java:490)
    at org.infinispan.interceptors.distribution.TriangleDistributionInterceptor.lambda$localPrimaryOwnerWrite$4(TriangleDistributionInterceptor.java:443)
    at org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextThenApply(BaseAsyncInterceptor.java:82)
    at org.infinispan.interceptors.distribution.TriangleDistributionInterceptor.localPrimaryOwnerWrite(TriangleDistributionInterceptor.java:422)
    at org.infinispan.interceptors.distribution.TriangleDistributionInterceptor.handleSingleKeyWriteCommand(TriangleDistributionInterceptor.java:392)
    at org.infinispan.interceptors.distribution.TriangleDistributionInterceptor.visitPutKeyValueCommand(TriangleDistributionInterceptor.java:113)
    at org.infinispan.commands.write.PutKeyValueCommand.acceptVisitor(PutKeyValueCommand.java:73)
    at org.infinispan.interceptors.BaseAsyncInterceptor.invokeNext(BaseAsyncInterceptor.java:55)
    at org.infinispan.interceptors.BaseAsyncInterceptor.lambda$new$0(BaseAsyncInterceptor.java:23)
    at org.infinispan.interceptors.InvocationSuccessFunction.apply(InvocationSuccessFunction.java:25)
    at org.infinispan.interceptors.impl.SimpleAsyncInvocationStage.addCallback(SimpleAsyncInvocationStage.java:70)
    at org.infinispan.interceptors.InvocationStage.thenApply(InvocationStage.java:45)
    at org.infinispan.interceptors.BaseAsyncInterceptor.asyncInvokeNext(BaseAsyncInterceptor.java:225)
    at org.infinispan.interceptors.impl.EntryWrappingInterceptor.setSkipRemoteGetsAndInvokeNextForDataCommand(EntryWrappingInterceptor.java:734)
    at org.infinispan.interceptors.impl.EntryWrappingInterceptor.visitPutKeyValueCommand(EntryWrappingInterceptor.java:337)
    at org.infinispan.commands.write.PutKeyValueCommand.acceptVisitor(PutKeyValueCommand.java:73)
    at org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextAndFinally(BaseAsyncInterceptor.java:151)
    at org.infinispan.interceptors.locking.AbstractLockingInterceptor.lambda$nonTxLockAndInvokeNext$1(AbstractLockingInterceptor.java:297)
    at org.infinispan.interceptors.SyncInvocationStage.addCallback(SyncInvocationStage.java:42)
    at org.infinispan.interceptors.InvocationStage.andHandle(InvocationStage.java:65)
    at org.infinispan.interceptors.locking.AbstractLockingInterceptor.nonTxLockAndInvokeNext(AbstractLockingInterceptor.java:292)
    at org.infinispan.interceptors.locking.AbstractLockingInterceptor.visitNonTxDataWriteCommand(AbstractLockingInterceptor.java:128)
    at org.infinispan.interceptors.locking.NonTransactionalLockingInterceptor.visitDataWriteCommand(NonTransactionalLockingInterceptor.java:40)
    at org.infinispan.interceptors.locking.AbstractLockingInterceptor.visitPutKeyValueCommand(AbstractLockingInterceptor.java:82)
    at org.infinispan.commands.write.PutKeyValueCommand.acceptVisitor(PutKeyValueCommand.java:73)
    at org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextAndHandle(BaseAsyncInterceptor.java:184)
    at org.infinispan.statetransfer.StateTransferInterceptor.handleNonTxWriteCommand(StateTransferInterceptor.java:309)
    at org.infinispan.statetransfer.StateTransferInterceptor.handleWriteCommand(StateTransferInterceptor.java:252)
    at org.infinispan.statetransfer.StateTransferInterceptor.visitPutKeyValueCommand(StateTransferInterceptor.java:96)
    at org.infinispan.commands.write.PutKeyValueCommand.acceptVisitor(PutKeyValueCommand.java:73)
    at org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextAndFinally(BaseAsyncInterceptor.java:151)
    at org.infinispan.interceptors.impl.CacheMgmtInterceptor.updateStoreStatistics(CacheMgmtInterceptor.java:220)
    at org.infinispan.interceptors.impl.CacheMgmtInterceptor.visitPutKeyValueCommand(CacheMgmtInterceptor.java:182)
    at org.infinispan.commands.write.PutKeyValueCommand.acceptVisitor(PutKeyValueCommand.java:73)
    at org.infinispan.interceptors.BaseAsyncInterceptor.invokeNext(BaseAsyncInterceptor.java:55)
    at org.infinispan.interceptors.DDAsyncInterceptor.handleDefault(DDAsyncInterceptor.java:54)
    at org.infinispan.interceptors.DDAsyncInterceptor.visitPutKeyValueCommand(DDAsyncInterceptor.java:60)
    at org.infinispan.commands.write.PutKeyValueCommand.acceptVisitor(PutKeyValueCommand.java:73)
    at org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextAndExceptionally(BaseAsyncInterceptor.java:124)
    at org.infinispan.interceptors.impl.InvocationContextInterceptor.visitCommand(InvocationContextInterceptor.java:90)
    at org.infinispan.interceptors.BaseAsyncInterceptor.invokeNext(BaseAsyncInterceptor.java:57)
    at org.infinispan.interceptors.DDAsyncInterceptor.handleDefault(DDAsyncInterceptor.java:54)
    at org.infinispan.interceptors.DDAsyncInterceptor.visitPutKeyValueCommand(DDAsyncInterceptor.java:60)
    at org.infinispan.commands.write.PutKeyValueCommand.acceptVisitor(PutKeyValueCommand.java:73)
    at org.infinispan.interceptors.DDAsyncInterceptor.visitCommand(DDAsyncInterceptor.java:50)
    at org.infinispan.interceptors.impl.AsyncInterceptorChainImpl.invoke(AsyncInterceptorChainImpl.java:248)
    at org.infinispan.cache.impl.CacheImpl.executeCommandAndCommitIfNeeded(CacheImpl.java:1915)
    at org.infinispan.cache.impl.CacheImpl.put(CacheImpl.java:1430)
    at org.infinispan.cache.impl.CacheImpl.put(CacheImpl.java:2040)
    at org.infinispan.cache.impl.CacheImpl.put(CacheImpl.java:1415)
    at org.infinispan.cache.impl.CacheImpl.put(CacheImpl.java:235)
    at org.infinispan.cache.impl.AbstractDelegatingCache.put(AbstractDelegatingCache.java:116)
    at org.infinispan.cache.impl.EncoderCache.put(EncoderCache.java:195)
    at org.infinispan.spring.common.provider.SpringCache.put(SpringCache.java:159)
    at org.infinispan.spring.common.session.AbstractInfinispanSessionRepository.updateTTL(AbstractInfinispanSessionRepository.java:112)
    at org.infinispan.spring.common.session.AbstractInfinispanSessionRepository.lambda$getSession$1(AbstractInfinispanSessionRepository.java:105)
    at java.base/java.util.Optional.map(Optional.java:265)
    at org.infinispan.spring.common.session.AbstractInfinispanSessionRepository.getSession(AbstractInfinispanSessionRepository.java:105)
    at org.infinispan.spring.common.session.AbstractInfinispanSessionRepository.findById(AbstractInfinispanSessionRepository.java:79)
    at org.infinispan.spring.common.session.AbstractInfinispanSessionRepository.findById(AbstractInfinispanSessionRepository.java:32)
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getRequestedSession(SessionRepositoryFilter.java:351)
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:289)
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:192)
    at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:244)
    at xxx.MaxSimultaneousRequestsFilter.getKey(MaxSimultaneousRequestsFilter.java:266)
    at xxx.MaxSimultaneousRequestsFilter.doFilter(MaxSimultaneousRequestsFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at xxx.LoginFilter.doFilter(LoginFilter.java:49)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at xxx.BigIPFilter.doFilter(BigIPFilter.java:41)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at xxx.EncodingFilter.doFilter(EncodingFilter.java:36)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:141)
    at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:82)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at xxx.ExcludeSessionRepositoryFilter.doFilter(ExcludeSessionRepositoryFilter.java:78)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.jboss.marshalling.TraceInformation: null

Using the DIST_SYNC mode for sessions should be fine.对会话使用 DIST_SYNC 模式应该没问题。

If a ConcurrentModificationException is thrown while serializing a session attribute, then it's a sign that the application is modifying an attribute value after inserting it in the session, and it should not do that.如果在序列化 session 属性时抛出ConcurrentModificationException ,则表明应用程序在将属性值插入 session 后正在修改该属性值,并且不应这样做。

If a ConcurrentModificationException happens while serializing the session itself, then it's likely a bug in the Infinispan Spring Session integration.如果在序列化 session 本身时发生ConcurrentModificationException ,则可能是 Infinispan Spring Session 集成中的错误。 Same if the ConcurrentModificationException is not related to serialization at all.如果ConcurrentModificationException根本与序列化无关,则相同。 I suggest posting the full stack trace in your question, or registering an account for the Infinispan Zulip Chat and posting the exception there.我建议在您的问题中发布完整的堆栈跟踪,或者为Infinispan Zulip Chat注册一个帐户并在那里发布异常。

As a final note, Infinispan 9.4.20 is pretty old, and an eventual bug fix is probably going to land only in Infinispan 12.x.最后一点,Infinispan 9.4.20 已经很老了,最终的错误修复可能只会在 Infinispan 12.x 中出现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Infinispan + Spring 启动 - 不缓存 - Infinispan + Spring Boot - Doesn't Cache springboot + infinispan 失效模式:如何与共享缓存存储一起使用? - springboot + infinispan invalidation mode : How can used with shared cache storage? Spring Session + Redis + Infinispan在会话范围内缓存失败 - Spring session + Redis + Infinispan caching in session scope fail Spring 引导应用程序的 Hibernate 缓存(Infinispan,Hazelcast,理想可扩展) - Hibernate Cache for Spring Boot Application (Infinispan, Hazelcast, ideally scalable) 使用@Cacheable Spring批注并手动添加到Infinispan Cache - Using @Cacheable Spring annotation and manually add to Infinispan Cache Infinispan - 没有删除缓存的选项吗? - Infinispan - is there no option to delete a cache? 当使用 Spring Session 外部化 session 存储时,Infinispan 没有编组整个 RefreshableKeycloakSecurityContext - Infinispan is not marshalling the whole RefreshableKeycloakSecurityContext when using Spring Session to externalize the session store infinispan 缓存可以在使用 hibernate 的同一 Spring Boot 应用程序的多个实例之间共享吗? - Can the infinispan cache be shared among multiple instances of the same spring boot application using hibernate? Infinispan 缓存放置不在循环中工作 - Infinispan cache put is not working in loop 适用于 Spring 引导 2.4.3 的 Infinispan 版本 - Infinispan Version for Spring Boot 2.4.3
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM