【问题标题】:Keycloak: remote-store configuration for dedicated Infinispan clusterKeycloak:专用 Infinispan 集群的远程存储配置
【发布时间】:2019-12-19 09:20:50
【问题描述】:

最近,我强化了我的 Keycloak 部署,将专用 Infinispan 集群用作 remote-store,为 Keycloak 的各种缓存提供额外的持久层。更改本身进行得相当顺利,尽管在进行此更改后,由于expired_code 错误消息,我们开始看到很多登录错误:

WARN [org.keycloak.events] (default task-2007) type=LOGIN_ERROR, realmId=my-realm, clientId=null, userId=null, ipAddress=192.168.50.38, error=expired_code, restart_after_timeout=true

此错误消息通常会在很短的时间内重复数十次,并且来自同一个 IP 地址。造成这种情况的原因似乎是最终用户的浏览器在登录时无限重定向,直到浏览器本身停止循环。

我已经看到各种 GitHub 问题 (https://github.com/helm/charts/issues/8355) 也记录了这种行为,并且一致认为这是由于 Keycloak 集群无法通过 JGroups 正确发现其成员造成的。

当您考虑到某些 Keycloak 缓存分布在 standalone-ha.xml 内的默认配置中的 Keycloak 节点时,这种解释是有道理的。但是,我已将这些缓存修改为本地缓存,其中 remote-store 指向我的新 Infinispan 集群,并且我相信我对它的工作原理做出了一些不正确的假设,导致此错误开始发生。

这是我的 Keycloak 缓存的配置方式:

<subsystem xmlns="urn:jboss:domain:infinispan:7.0">
    <cache-container name="keycloak" module="org.keycloak.keycloak-model-infinispan">
        <transport lock-timeout="60000"/>
        <local-cache name="realms">
            <object-memory size="10000"/>
        </local-cache>
        <local-cache name="users">
            <object-memory size="10000"/>
        </local-cache>
        <local-cache name="authorization">
            <object-memory size="10000"/>
        </local-cache>
        <local-cache name="keys">
            <object-memory size="1000"/>
            <expiration max-idle="3600000"/>
        </local-cache>
        <local-cache name="sessions">
            <remote-store cache="sessions" remote-servers="remote-cache" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                    true
                </property>
                <property name="marshaller">
                    org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
            </remote-store>
        </local-cache>
        <local-cache name="authenticationSessions">
            <remote-store cache="authenticationSessions" remote-servers="remote-cache" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                    true
                </property>
                <property name="marshaller">
                    org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
            </remote-store>
        </local-cache>
        <local-cache name="offlineSessions">
            <remote-store cache="offlineSessions" remote-servers="remote-cache" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                    true
                </property>
                <property name="marshaller">
                    org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
            </remote-store>
        </local-cache>
        <local-cache name="clientSessions">
            <remote-store cache="clientSessions" remote-servers="remote-cache" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                    true
                </property>
                <property name="marshaller">
                    org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
            </remote-store>
        </local-cache>
        <local-cache name="offlineClientSessions">
            <remote-store cache="offlineClientSessions" remote-servers="remote-cache" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                    true
                </property>
                <property name="marshaller">
                    org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
            </remote-store>
        </local-cache>
        <local-cache name="loginFailures">
            <remote-store cache="loginFailures" remote-servers="remote-cache" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                    true
                </property>
                <property name="marshaller">
                    org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
            </remote-store>
        </local-cache>
        <local-cache name="actionTokens">
            <remote-store cache="actionTokens" remote-servers="remote-cache" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                    true
                </property>
                <property name="marshaller">
                    org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
            </remote-store>
        </local-cache>
        <replicated-cache name="work">
            <remote-store cache="work" remote-servers="remote-cache" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                    true
                </property>
                <property name="marshaller">
                    org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
            </remote-store>
        </replicated-cache>
    </cache-container>
    <cache-container name="server" aliases="singleton cluster" default-cache="default" module="org.wildfly.clustering.server">
        <transport lock-timeout="60000"/>
        <replicated-cache name="default">
            <transaction mode="BATCH"/>
        </replicated-cache>
    </cache-container>
    <cache-container name="web" default-cache="dist" module="org.wildfly.clustering.web.infinispan">
        <transport lock-timeout="60000"/>
        <distributed-cache name="dist">
            <locking isolation="REPEATABLE_READ"/>
            <transaction mode="BATCH"/>
            <file-store/>
        </distributed-cache>
    </cache-container>
    <cache-container name="ejb" aliases="sfsb" default-cache="dist" module="org.wildfly.clustering.ejb.infinispan">
        <transport lock-timeout="60000"/>
        <distributed-cache name="dist">
            <locking isolation="REPEATABLE_READ"/>
            <transaction mode="BATCH"/>
            <file-store/>
        </distributed-cache>
    </cache-container>
    <cache-container name="hibernate" module="org.infinispan.hibernate-cache">
        <transport lock-timeout="60000"/>
        <local-cache name="local-query">
            <object-memory size="10000"/>
            <expiration max-idle="100000"/>
        </local-cache>
        <invalidation-cache name="entity">
            <transaction mode="NON_XA"/>
            <object-memory size="10000"/>
            <expiration max-idle="100000"/>
        </invalidation-cache>
        <replicated-cache name="timestamps"/>
    </cache-container>
</subsystem>

请注意,与默认的standalone-ha.xml 配置文件相比,此缓存配置的大部分内容都没有改变。我在这里所做的更改是将以下缓存更改为 local 并将它们指向我的远程 Infinispan 集群:

  • sessions
  • authenticationSessions
  • offlineSessions
  • clientSessions
  • offlineClientSessions
  • loginFailures
  • actionTokens
  • work

这是我的remote-cache 服务器的配置:

<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
    <!-- Default socket bindings from standalone-ha.xml are not listed here for brevity -->
    <outbound-socket-binding name="remote-cache">
        <remote-destination host="${env.INFINISPAN_HOST}" port="${remote.cache.port:11222}"/>
    </outbound-socket-binding>
</socket-binding-group>

这是我在 Infinispan 端配置缓存的方式:

<subsystem xmlns="urn:infinispan:server:core:9.4" default-cache-container="clustered">
    <cache-container name="clustered" default-cache="default">
        <transport lock-timeout="60000"/>
        <global-state/>
        <replicated-cache-configuration name="replicated-keycloak" mode="SYNC">
            <locking acquire-timeout="3000" />
        </replicated-cache-configuration>
        <replicated-cache name="work" configuration="replicated-keycloak"/>
        <replicated-cache name="sessions" configuration="replicated-keycloak"/>
        <replicated-cache name="authenticationSessions" configuration="replicated-keycloak"/>
        <replicated-cache name="clientSessions" configuration="replicated-keycloak"/>
        <replicated-cache name="offlineSessions" configuration="replicated-keycloak"/>
        <replicated-cache name="offlineClientSessions" configuration="replicated-keycloak"/>
        <replicated-cache name="actionTokens" configuration="replicated-keycloak"/>
        <replicated-cache name="loginFailures" configuration="replicated-keycloak"/>
    </cache-container>
</subsystem>

我相信我对本地缓存与远程存储的工作方式做出了一些错误的假设,我希望有人能够为我解决这个问题。我的目的是让 Infinispan 集群成为所有 Keycloak 缓存的真实来源。通过使每个缓存都本地化,我假设数据将通过 Infinispan 集群复制到每个 Keycloak 节点,这样对 keycloak-0 上的本地 authenticationSessions 缓存的写入将通过 Infinispan 集群同步持久化到 keycloak-1

我认为正在发生的事情是,写入 Keycloak 上的本地缓存与将该值持久保存到远程 Infinispan 集群方面并不同步。换句话说,当对authenticationSessions缓存执行写操作时,它在等待将该值写入Infinispan集群时不会阻塞,因此在另一个Keycloak节点上立即读取该数据会导致缓存未命中,在本地和 Infinispan 集群中。

我正在寻找一些帮助来确定我当前的配置导致此问题的原因,并澄清remote-store 的行为 - 有没有办法将缓存写入由@987654348 支持的本地缓存@要同步?如果没有,有没有更好的方法来做我在这里想要完成的事情?

其他一些可能相关的细节:

  • Keycloak 和 Infinispan 都部署到 Kubernetes 集群中的同一个命名空间。
  • 我正在使用 KUBE_PING 进行 JGroups 发现。
  • 使用 Infinispan 控制台,我能够验证复制到所有 Infinispan 节点的所有缓存中是否有一定数量的条目 - 它们并非完全未使用。
  • 如果我向一个 Keycloak 节点添加一个新领域,它会成功显示在其他 Keycloak 节点上,这让我相信 work 缓存正在跨所有 Keycloak 节点传播。
  • 如果我登录到一个 Keycloak 节点,我的会话将保留在其他 Keycloak 节点上,这使我相信会话相关的缓存正在跨所有 Keycloak 节点传播。
  • 我使用 Keycloak 的粘性会话作为临时解决方案,但我相信修复这些底层缓存问题是一个更持久的解决方案。

提前致谢!

【问题讨论】:

标签: keycloak infinispan


【解决方案1】:

在集群中配置 Keycloak 时,我将尝试澄清一些需要牢记的要点。

谈到“无限重定向”的主题,我多年前在开发环境中遇到过类似的问题。虽然 keycloak 团队已经纠正了几个与无限循环相关的错误(例如KEYCLOAK-5856KEYCLOAK-5022KEYCLOAK-4717KEYCLOAK-4552KEYCLOAK-3878),但有时它是由于配置问题而发生的。

检查站点是否为 HTTPS 的一件事是也通过 HTTPS 访问 Keycloak 服务器。

我记得当 Keycloak 放置在 HTTPS 反向代理之后并且所需的标头没有传播到 Keycloak(标头 X-FOWARDED...)时,我遇到了与无限循环类似的问题。环境设置好就解决了。当集群中的节点发现无法正常工作(JGroups)时,可能会发生类似的问题。

关于错误信息“expired_code”,我会验证每个节点的时钟是否同步,因为它会导致这种过期令牌/代码错误。

现在更好地理解了您的配置,将“本地缓存”模式与远程存储一起使用似乎并不合适,指向 infinispan 集群。

虽然通常共享存储(例如远程缓存)通常与失效缓存一起使用,以避免集群复制完整数据(请参阅可以在此处应用的注释https://developer.jboss.org/message/986847#986847) ,与分布式缓存或失效缓存可能没有太大区别。

我相信带有远程存储的分布式缓存会更好地应用(或无效缓存以避免将大量数据复制给所有者)但是我无法确保“本地缓存”如何与远程存储一起使用(共享)因为我从未尝试过这种配置。 我会首先选择测试分布式缓存或失效缓存,根据它如何处理被驱逐/失效的数据。通常,本地缓存不会与集群中的其他远程节点同步。如果这种实现方式在内存中保留了一个本地映射,那么即使远程存储中的数据被修改,这些更改也可能在某些情况下不会反映出来。 我可以给你一个 Jmeter 测试文件,你可以使用,这样你就可以尝试使用这两种配置执行自己的测试。

回到你的配置主题,除了复制缓存有一定的限制,通常比只将数据复制到定义的所有者(复制的那些写入所有节点)。还有一个称为分散缓存的变体,它性能更好,但例如缺少事务支持(您可以在此处查看比较图表https://infinispan.org/docs/stable/user_guide/user_guide.html#which_cache_mode_should_i_use)。 由于需要发送的复制消息的数量,复制通常只在小型集群(8 或 10 台服务器以下)中表现良好。分布式缓存允许 Infinispan 通过按条目定义多个副本来线性扩展。

配置您尝试执行的类型而不是类似于 Keycloak (standalone-ha.xml) 建议的配置的主要原因是,当您需要独立扩展 infinispan 集群时应用程序或使用 infinispan 作为持久存储。

我将解释 Keycloak 是如何管理其缓存的,以及它是如何将其分为两组或三组的,以便您更好地了解您需要的配置。

通常,要在集群中配置 Keycloak,只需在 HA 模式下提升和配置 Keycloak,就像使用传统的 Wildfly 实例一样。如果观察 keycloak 安装中的standalone.xml 和standalone-ha.xml 之间的差异,就会注意到“Jgroups”、“modcluster”中添加了基本支持,并且缓存是分布式的(以前是本地的) ) 在 Wildfly / Keycloak (HA) 中的节点之间。

详细说明

  • 添加了jgroups子系统,它将负责连接集群节点并在集群中进行消息/通信。 JGroups 提供网络通信能力、可靠通信和其他功能,如节点发现、点对点通信、多播通信、故障检测和集群节点之间的数据传输。
  • EJB3 缓存从简单缓存(在本地内存中,没有事务处理)变为分布式。但是,根据我扩展该项目的经验,我会确保 Keycloak 项目不需要使用 EJB3。
  • 缓存:“领域”、“用户”、“授权”和“密钥”保留在本地,因为它们仅用于减少数据库的负载。
  • cache: "work" 变为 REPLICATED,因为它是 Keycloak 用来通知集群节点缓存条目必须被驱逐/无效的缓存条目,因为它的状态已被修改。
  • 缓存“sessions”、“authenticationSessions”、“offlineSessions”、“clientSessions”、“offlineSessions”、“loginFailures”和“actionTokens”变为 DISTRIBUTED,因为它们的性能优于复制缓存(参见 https://infinispan.org/docs/stable/user_guide/user_guide.html#which_cache_mode_should_i_use),因为您只需将数据复制给所有者。
  • keycloak 对其默认 HA 配置提出的其他更改是分发“web”和“ejb”(及以上)缓存容器,并将“休眠”缓存更改为“无效缓存”(如本地缓存但有失效同步)。

我认为您的缓存配置应该定义为“分布式缓存”,用于“会话”、“身份验证会话”、“离线会话”、“客户端会话”、“离线客户端会话”、“登录失败”和“动作令牌”等缓存(而不是“本地”)。但是,由于您使用的是远程共享存储,因此您应该对其进行测试,看看它是如何工作的。

此外,名为“work”的缓存应为“replicated-cache”,其他(“keys”、“authorization”、“realms”和“users”)应定义为“local-cache”。

在您的 infinispan 集群中,您可以将其定义为“分布式缓存”(或“复制缓存”)。

记住:

在复制缓存中,集群中的所有节点都持有所有键,即如果一个 key 存在于一个节点上,它也将存在于所有其他节点上。在一个 分布式缓存,维护多个副本以提供 冗余和容错,但是这通常要少得多 比集群中的节点数。分布式缓存提供 比复制缓存更大程度的可扩展性。 分布式缓存还能够透明地定位跨域的键 集群,并提供 L1 缓存,用于快速本地读取状态 这是远程存储的。您可以在相关的用户指南中阅读更多信息 章节。

Infinispan 文档。参考:cache mode

正如 Keycloak (6.0) 文档所说:

Keycloak 有两种类型的缓存。一种类型的缓存位于前面 数据库以减少数据库上的负载并降低整体 通过将数据保存在内存中来缩短响应时间。领域、客户、角色和 用户元数据保存在这种类型的缓存中。这个缓存是本地的 缓存。本地缓存不使用复制,即使您在 具有更多 Keycloak 服务器的集群。相反,他们只保留副本 在本地,如果条目被更新,则将无效消息发送到 集群的其余部分和条目被驱逐。有单独的 复制缓存工作,任务是发送失效消息 向整个集群告知应该从本地驱逐哪些条目 缓存。这大大减少了网络流量,使事情变得高效, 并避免通过网络传输敏感元数据。

第二种类型的缓存处理管理用户会话,离线 令牌,并跟踪登录失败,以便服务器可以 检测密码网络钓鱼和其他攻击。这些中保存的数据 缓存是临时的,仅在内存中,但可能会跨 集群。

文档。参考:cache configuration

如果您想阅读另一个好文档,可以查看“cross-dc”部分(cross-dc mode)尤其是“3.4.6 Infinispan 缓存”部分(infinispan cache

我尝试使用 Keycloak 6.0.1 和 Infinispan 9.4.11.Final,这是我的测试配置(基于 Standalone-ha.xml 文件)。

Keycloak infinispan 子系统

    <subsystem xmlns="urn:jboss:domain:infinispan:8.0">
        <cache-container name="keycloak" module="org.keycloak.keycloak-model-infinispan">
            <transport lock-timeout="60000"/>
            <local-cache name="realms">
                <object-memory size="10000"/>
            </local-cache>
            <local-cache name="users">
                <object-memory size="10000"/>
            </local-cache>
            <distributed-cache name="sessions" owners="1" remote-timeout="30000">
                <remote-store cache="sessions" remote-servers="remote-cache" socket-timeout="60000" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                true
                </property>
                <property name="marshaller">
org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
                </remote-store>
                </distributed-cache>
            <distributed-cache name="authenticationSessions" owners="1" remote-timeout="30000">
                <remote-store cache="authenticationSessions" remote-servers="remote-cache" socket-timeout="60000" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                true
                </property>
                <property name="marshaller">
org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
                </remote-store>
                </distributed-cache>
            <distributed-cache name="offlineSessions" owners="1" remote-timeout="30000">
                <remote-store cache="offlineSessions" remote-servers="remote-cache" socket-timeout="60000" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
true
                </property>
                <property name="marshaller">
org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
                </remote-store>
                </distributed-cache>
            <distributed-cache name="clientSessions" owners="1" remote-timeout="30000">
                <remote-store cache="clientSessions" remote-servers="remote-cache" socket-timeout="60000" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
true
                </property>
                <property name="marshaller">
org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
                </remote-store>
                </distributed-cache>
            <distributed-cache name="offlineClientSessions" owners="1" remote-timeout="30000">
                <remote-store cache="offlineClientSessions" remote-servers="remote-cache" socket-timeout="60000" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                true
                </property>
                <property name="marshaller">
org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
                </remote-store>
                </distributed-cache>
            <distributed-cache name="loginFailures" owners="1" remote-timeout="30000">
                <remote-store cache="loginFailures" remote-servers="remote-cache" socket-timeout="60000" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                true
                </property>
                <property name="marshaller">
org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
                </remote-store>
                </distributed-cache>
            <replicated-cache name="work"/>
            <local-cache name="authorization">
                <object-memory size="10000"/>
            </local-cache>
            <local-cache name="keys">
                <object-memory size="1000"/>
                <expiration max-idle="3600000"/>
            </local-cache>
            <distributed-cache name="actionTokens" owners="1" remote-timeout="30000">
                <remote-store cache="actionTokens" remote-servers="remote-cache" socket-timeout="60000" fetch-state="false" passivation="false" preload="false" purge="false" shared="true">
                <property name="rawValues">
                true
                </property>
                <property name="marshaller">
org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory
                </property>
                </remote-store>
                <object-memory size="-1"/>
                <expiration max-idle="-1" interval="300000"/>
            </distributed-cache>
         </cache-container>

Keycloak 套接字绑定

<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
    <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
    <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
    <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
    <socket-binding name="http" port="${jboss.http.port:8080}"/>
    <socket-binding name="https" port="${jboss.https.port:8443}"/>
    <socket-binding name="jgroups-mping" interface="private" multicast-address="${jboss.default.multicast.address:230.0.0.4}" multicast-port="45700"/>
    <socket-binding name="jgroups-tcp" interface="private" port="7600"/>
    <socket-binding name="jgroups-udp" interface="private" port="55200" multicast-address="${jboss.default.multicast.address:230.0.0.4}" multicast-port="45688"/>
    <socket-binding name="modcluster" multicast-address="${jboss.modcluster.multicast.address:224.0.1.105}" multicast-port="23364"/>
    <socket-binding name="txn-recovery-environment" port="4712"/>
    <socket-binding name="txn-status-manager" port="4713"/>
<outbound-socket-binding name="remote-cache">
<remote-destination host="my-server-domain.com" port="11222"/>  
</outbound-socket-binding>
    <outbound-socket-binding name="mail-smtp">
        <remote-destination host="localhost" port="25"/>
    </outbound-socket-binding>
</socket-binding-group>

Infinispan 集群配置

<subsystem xmlns="urn:infinispan:server:core:9.4" default-cache-container="clustered">
    <cache-container name="clustered" default-cache="default" statistics="true">
        <transport lock-timeout="60000"/>
        <global-state/>
        <distributed-cache-configuration name="transactional">
            <transaction mode="NON_XA" locking="PESSIMISTIC"/>
        </distributed-cache-configuration>
        <distributed-cache-configuration name="async" mode="ASYNC"/>
        <replicated-cache-configuration name="replicated"/>
        <distributed-cache-configuration name="persistent-file-store">
            <persistence>
                <file-store shared="false" fetch-state="true"/>
            </persistence>
        </distributed-cache-configuration>
        <distributed-cache-configuration name="indexed">
            <indexing index="LOCAL" auto-config="true"/>
        </distributed-cache-configuration>
        <distributed-cache-configuration name="memory-bounded">
            <memory>
                <binary size="10000000" eviction="MEMORY"/>
            </memory>
        </distributed-cache-configuration>
        <distributed-cache-configuration name="persistent-file-store-passivation">
            <memory>
                <object size="10000"/>
            </memory>
            <persistence passivation="true">
                <file-store shared="false" fetch-state="true">
                    <write-behind modification-queue-size="1024" thread-pool-size="1"/>
                </file-store>
            </persistence>
        </distributed-cache-configuration>
        <distributed-cache-configuration name="persistent-file-store-write-behind">
            <persistence>
                <file-store shared="false" fetch-state="true">
                    <write-behind modification-queue-size="1024" thread-pool-size="1"/>
                </file-store>
            </persistence>
        </distributed-cache-configuration>
        <distributed-cache-configuration name="persistent-rocksdb-store">
            <persistence>
                <rocksdb-store shared="false" fetch-state="true"/>
            </persistence>
        </distributed-cache-configuration>
        <distributed-cache-configuration name="persistent-jdbc-string-keyed">
            <persistence>
                <string-keyed-jdbc-store datasource="java:jboss/datasources/ExampleDS" fetch-state="true" preload="false" purge="false" shared="false">
                    <string-keyed-table prefix="ISPN">
                        <id-column name="id" type="VARCHAR"/>
                        <data-column name="datum" type="BINARY"/>
                        <timestamp-column name="version" type="BIGINT"/>
                    </string-keyed-table>
                    <write-behind modification-queue-size="1024" thread-pool-size="1"/>
                </string-keyed-jdbc-store>
            </persistence>
        </distributed-cache-configuration>
        <distributed-cache name="default"/>
        <replicated-cache name="repl" configuration="replicated"/>
        <replicated-cache name="work" configuration="replicated"/>
        <replicated-cache name="sessions" configuration="replicated"/>
        <replicated-cache name="authenticationSessions" configuration="replicated"/>
        <replicated-cache name="clientSessions" configuration="replicated"/>
        <replicated-cache name="offlineSessions" configuration="replicated"/>
        <replicated-cache name="offlineClientSessions" configuration="replicated"/>
        <replicated-cache name="actionTokens" configuration="replicated"/>
        <replicated-cache name="loginFailures" configuration="replicated"/>
    </cache-container>
</subsystem>

附:将属性“所有者”从 1 更改为您喜欢的值。

希望对你有所帮助。

【讨论】:

  • 感谢您的回复!您能帮我理解将远程存储用于复制缓存的行为吗?这意味着,给定缓存work(例如),如果它在所有 Keycloak 节点之间进行复制,并且它有一个远程存储指向一个专用的 infinispan 集群,该集群也在其所有节点之间复制,它的行为如何节点何时启动、关闭等?在实施时我应该担心竞争条件吗?
  • 嗨@MichaelParker,也许我误解了你试图做的配置,我会尝试重写答案并澄清如果我想在压力测试中测试的配置会是什么样子更改我的集群配置。目前,我有一个 HA 模式的 KC 集群,仅使用本地、分布式和复制缓存(没有专用的 Infinispan 集群)。
  • 感谢您的帮助!您更新的答案包含我正在寻找的信息。
  • 我将尝试使用您在共享远程存储中提供的信息来推进失效缓存。如果这不起作用,我认为使用复制缓存配置可能就足够了,因为我的集群相对较小。
  • 好的,迈克尔,让我们开始吧。也许我可以在下周尝试一些测试。让我们保持联系。
【解决方案2】:

各位,在这里交流非常好,令人难以置信的是,我的假设与 Michael 完全相同,我将本地缓存配置为使用远程存储,并希望密钥始终从远程存储中读取/写入,但显然它不是它的工作原理。

遗憾的是,从这里完成的所有交换中,我找不到为什么会这样,为什么我们不能将本地 infinispan 配置为仅充当远程 infinispan 的代理,从而使这些实例保持无状态并且更容易重新部署的过程。

【讨论】:

    猜你喜欢
    • 2018-02-03
    • 2014-03-16
    • 2021-12-30
    • 1970-01-01
    • 2018-05-25
    • 2013-09-23
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多