Keycloak:从嵌入式到远程 Infinispan 重建时到 Infinispan 集群的持久缓存同步超时

如何解决Keycloak:从嵌入式到远程 Infinispan 重建时到 Infinispan 集群的持久缓存同步超时

我正在将 keycloak (v.3.4.0 final) 从使用嵌入式 infinispan 切换到专用的远程 infinispan 集群 (v8.2.8.final)。我已经完成了升级过程,在较低的环境中使用 infinispan 集群作为远程存储,没有问题。在我的生产设置中,我在 InfinispanCacheInitializer 上遇到超时异常

Keycloak 发生错误的地方:https://github.com/keycloak/keycloak/blob/3.4.2.Final/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/InfinispanCacheInitializer.java#L117

ERROR [org.keycloak.models.sessions.infinispan.initializer.InfinispanCacheInitializer] (ServerService Thread Pool -- 54) ExecutionException when computed future. Errors: 13: java.util.concurrent.ExecutionException: java.util.concurrent.TimeoutExc
eption                                                                                                                                                                                                                                                                      
        at org.infinispan.distexec.DefaultExecutorService$distributedTaskPart.get(DefaultExecutorService.java:850)                                                                                                                                                          
        at org.keycloak.models.sessions.infinispan.initializer.InfinispanCacheInitializer.startLoading(InfinispanCacheInitializer.java:102)                                                                                                                                 
        at org.keycloak.models.sessions.infinispan.initializer.DBLockBasedCacheInitializer.startLoading(DBLockBasedCacheInitializer.java:75)                                                                                                                                
        at org.keycloak.models.sessions.infinispan.initializer.CacheInitializer.loadSessions(CacheInitializer.java:41)                                                                                                                                                      
        at org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory$2.run(InfinispanUserSessionProviderFactory.java:150)                                                                                                                                
        at org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction(KeycloakModelUtils.java:227)                                                                                                                                                                    
        at org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory.loadPersistentSessions(InfinispanUserSessionProviderFactory.java:137)                                                                                                               
        at org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory$1.onEvent(InfinispanUserSessionProviderFactory.java:108)                                                                                                                            
        at org.keycloak.services.DefaultKeycloakSessionFactory.publish(DefaultKeycloakSessionFactory.java:68)                                                                                                                                                               
        at org.keycloak.services.resources.KeycloakApplication$2.run(KeycloakApplication.java:165)                                                                                                                                                                          
        at org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction(KeycloakModelUtils.java:227)                                                                                                                                                                    
        at org.keycloak.services.resources.KeycloakApplication.<init>(KeycloakApplication.java:158)                                                                                                                                                                         
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)                                                                                                                                                                                            
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)                                                                                                                                                                     
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)                                                                                                                                                             
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)                                                                                                                                                                                                  
        at org.jboss.resteasy.core.ConstructorInjectorImpl.construct(ConstructorInjectorImpl.java:150)                                                                                                                                                                      
        at org.jboss.resteasy.spi.ResteasyProviderFactory.createProviderInstance(ResteasyProviderFactory.java:2298)                                                                                                                                                         
        at org.jboss.resteasy.spi.ResteasyDeployment.createApplication(ResteasyDeployment.java:340)                                                                                                                                                                         
        at org.jboss.resteasy.spi.ResteasyDeployment.start(ResteasyDeployment.java:253)                                                                                                                                                                                     
        at org.jboss.resteasy.plugins.server.servlet.ServletContainerdispatcher.init(ServletContainerdispatcher.java:120)                                                                                                                                                   
        at org.jboss.resteasy.plugins.server.servlet.HttpServletdispatcher.init(HttpServletdispatcher.java:36)                                                                                                                                                              
        at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:117)                                                                                                                                                           
        at org.wildfly.extension.undertow.security.RunAsLifecycleInterceptor.init(RunAsLifecycleInterceptor.java:78)                                                                                                                                                        
        at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:103)                                                                                                                                                           
        at io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start(ManagedServlet.java:250)                                                                                                                                                                   
        at io.undertow.servlet.core.ManagedServlet.createServlet(ManagedServlet.java:133)                                                                                                                                                                                   
        at io.undertow.servlet.core.DeploymentManagerImpl$2.call(DeploymentManagerImpl.java:565)                                                                                                                                                                            
        at io.undertow.servlet.core.DeploymentManagerImpl$2.call(DeploymentManagerImpl.java:536)                                                                                                                                                                            
        at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:42)                                                                                                                                           
        at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)                                                                                                                                                             
        at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)                                                                                                                              
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)                                                                                                       
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)                                                                                                       
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)                                                                                                       
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)                                                                                                       
        at io.undertow.servlet.core.DeploymentManagerImpl.start(DeploymentManagerImpl.java:578)                                                                                                                                                                             
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:100)                                                                                                                                             
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:81)                                                                                                                                                     
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)                                                                                                                                                                                          
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)                                                                                                                                                                                                         
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)                                                                                                                                                                                  
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)                                                                                                                                                                                  
        at java.lang.Thread.run(Thread.java:748)                                                                                                                                                                                                                            
        at org.jboss.threads.JBossthread.run(JBossthread.java:320)                                                                                                                                                                                                          
Caused by: java.util.concurrent.TimeoutException                                                                                                                                                                                                                            
        at java.util.concurrent.FutureTask.get(FutureTask.java:205)                                                                                                                                                                                                         
        at org.infinispan.commons.util.concurrent.NotifyingFutureImpl.get(NotifyingFutureImpl.java:88)                                                                                                                                                                      
        at org.infinispan.distexec.DefaultExecutorService$LocaldistributedTaskPart.getResult(DefaultExecutorService.java:1083)                                                                                                                                              
        at org.infinispan.distexec.DefaultExecutorService$distributedTaskPart.innerGet(DefaultExecutorService.java:868)                                                                                                                                                     
        at org.infinispan.distexec.DefaultExecutorService$distributedTaskPart.get(DefaultExecutorService.java:848)                                                                                                                                                          
        ... 44 more

概述

  • Keycloak 版本:3.4.0.final(知道这是一个旧版本 - 并与自定义一起使用 实施 - 不容易升级
    • 启动脚本:ExecStart={{ keycloak_jboss_home }}/bin/standalone.sh -b 使用 standalone.xml
  • Infinispan 版本:8.2.8.final
  • 从嵌入式本地缓存切换到以下缓存的远程存储配置:
    • 用户(分布式)
    • 会话(复制)
    • authenticationSessions(复制)
    • offlinesessions(复制)
    • 登录失败(重复)
    • 授权(复制)
  • offline_user_session 计数:约 300 万

为了从数据库测试这个大小的缓存同步,我更新了 standalone.xml 和 standalone.conf 文件中的超时配置

keycloak/keycloak-3.4.0.Final/standalone/configuration/standalone.xml 将协调器超时更新为 3 小时并注释掉查询超时

<subsystem xmlns="urn:jboss:domain:transactions:4.0">                                                                                                                                                                                             
    <core-environment>                                                                                                                                                                                                                            
        <process-id>                                                                                                                                                                                                                              
            <uuid/>                                                                                                                                                                                                                               
         </process-id>                                                                                                                                                                                                                             
    </core-environment>                                                                                                                                                                                                                           
    <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>                                                                                                                                  
    <object-store path="tx-object-store" relative-to="jboss.server.data.dir"/>                                                                                                                                                                    
    <coordinator-environment default-timeout="10800"/>                                                                                                                                                                                            
 </subsystem> 

....
....
..

<!-- <timeout>                                                                                                                                                                                                                        
    <query-timeout>15</query-timeout>                                                                                                                                                                                                 
</timeout>-->   

/keycloak/keycloak-3.4.0.Final/bin/standalone.conf 将阻塞超时添加到 JAVA_OPTS

JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=$JBOSS_MODULES_SYstem_PKGS -Djava.awt.headless=true -Djboss.as.management.blocking.timeout=10800"  

我想指出的是,在最初几次尝试使其工作后,当恢复使用 keycloak 节点上的嵌入式缓存时,数据同步良好,在大约 1.5 小时内没有任何超时错误

keycloak 启动后大约需要 60 分钟才能开始同步离线用户会话。查看 keycloak 正在运行的查询,我可以看到在开始将 offline_user_session 记录同步到 offlinesessions 缓存后大约 5-10 分钟发生超时错误

enter image description here

在超时之前运行的查询是:

  1. delete from OFFLINE_CLIENT_SESSION where not (exists (select persistent1_.USER_SESSION_ID from OFFLINE_USER_SESSION persistent1_ where persistent1_.USER_SESSION_ID=OFFLINE_CLIENT_SESSION.USER_SESSION_ID))

  2. update OFFLINE_USER_SESSION set LAST_SESSION_REFRESH=$1

  3. DELETE FROM jgroupsPING WHERE own_addr=$1 AND cluster_name=$2

  4. select count(persistent0_.OFFLINE_FLAG) as col_0_0_ from OFFLINE_USER_SESSION persistent0_ where persistent0_.OFFLINE_FLAG=$1

  5. select userrolema0_.ROLE_ID as col_0_0_ from USER_ROLE_MAPPING userrolema0_ where userrolema0_.USER_ID=$1

  6. select userentity0_.ID as ID1_76_,userentity0_.CREATED_TIMESTAMP as CREATED_2_76_,userentity0_.EMAIL as EMAIL3_76_,userentity0_.EMAIL_CONSTRAINT as EMAIL_CO4_76_,userentity0_.EMAIL_VERIFIED as EMAIL_VE5_76_,userentity0_.ENABLED as ENABLED6_76_,userentity0_.FEDERATION_LINK as FEDERATI7_76_,userentity0_.FirsT_NAME as FirsT_NA8_76_,userentity0_.LAST_NAME as LAST_NAM9_76_,userentity0_.NOT_BEFORE as NOT_BEF10_76_,userentity0_.REALM_ID as REALM_I11_76_,userentity0_.SERVICE_ACCOUNT_CLIENT_LI

  7. select attributes0_.USER_ID as USER_ID4_72_0_,attributes0_.ID as ID1_72_0_,attributes0_.ID as ID1_72_1_,attributes0_.NAME as NAME2_72_1_,attributes0_.USER_ID as USER_ID4_72_1_,attributes0_.VALUE as VALUE3_72_1_ from USER_ATTRIBUTE attributes0_ where attributes0_.USER_ID=$1

  8. select persistent0_.OFFLINE_FLAG as OFFLINE_1_47_,persistent0_.USER_SESSION_ID as USER_SES2_47_,persistent0_.DATA as DATA3_47_,persistent0_.LAST_SESSION_REFRESH as LAST_SES4_47_,persistent0_.REALM_ID as REALM_ID5_47_,persistent0_.USER_ID as USER_ID6_47_ from OFFLINE_USER_SESSION persistent0_ where persistent0_.OFFLINE_FLAG=$1 order by persistent0_.USER_SESSION_ID limit $2 offset $3

我设置了 Infinispan WebConsole UI,所以我可以看到缓存同步的进度。每次收到 15k 个条目(大约 300 万个)

enter image description here

我不肯定这里的问题,因为从数据库同步离线会话对于嵌入式版本工作正常,但对于远程 infinispan 启动,它似乎有问题,要么是查询的批处理,要么是我的另一种配置infinispan侧的keycloak中的任何一个缺失。

解决方法

将 keycloak 版本升级到 5.0 解决了缓存同步因期货而超时的问题。升级 4.7 之后的主要版本 -> 在缓存同步时间方面有一些代码更改,现在大约 300 万条记录需要大约 30-40 分钟。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?