Keycloak - Infinispan Redis缓存商店

tux*_*tux 7 jboss infinispan wildfly keycloak

目前在standalone-ha模式下设置keycloak集群,以便能够在docker swarm上运行.在keycloak中,用户会话缓存在嵌入式infinispan存储中,infinispan可以配置为跨群集的分布式缓存.

我还将所有者设置为2,但问题是..在缩小规模期间,用户会话可能会丢失,如果包含缓存的所有者都在缩小期间被杀死.

我也读过有关Infinispan Redis缓存存储的信息,但我不知道如何配置它.

问题1:是否可以将Keycloak Infinispan配置为用户Redis商店?

问题2:如果不可能,有没有办法可以克服这个问题?

任何的意见都将会有帮助.

Gui*_*ira 8

由于这个 PR https://github.com/keycloak/keycloak/commit/056ba75a72b1595ca9fa471f5693201fd5b2c7ae默认情况下(Keycloak 最新版本 6.0.1),Infinispan Connection SPI它使用InfinispanChangelogBasedTransaction.java了一个非常特殊的使用 a CacheDecorator.javawhich will skipCacheStore。这意味着无论您是否配置具有持久性的存储,该存储都将被忽略。

为了实现您想要的,除了配置商店之外,您还必须在此处自定义大部分 SPI https://github.com/keycloak/keycloak/tree/master/model/infinispan/src/main/resources/META -INF/services以确保 Keycloak 将使用缓存存储。

这也不容易,因为这个过程涉及很多额外的好处,例如,因为 Keycloak 正在使用 Jboss 的 Marshaller,如果你自定义这个 SPI,你将不得不携带大部分org.keycloak.models.sessions.infinispan包并注册你的模块来制作确保 Wildfly 能够看到要编组的实体。

还有一点就是你应该在Redis中配置大部分缓存指向一个公用的数据库,除了authenticationSessions不能和 同一个数据库sessions,否则会出现像RootAuthenticationSesssionEntity被发现但预期是 的冲突SessionEntityWrapper

重新开始,过程会很痛苦,但如果你敢于去做,我是这样实现的:

  • 引入了一个自定义 InfinispanConnectionProviderFactory 以便拥有使用 infinispan 配置的完整功能,然后配置我的容器,例如:
private Configuration getRedisConfiguration(int database) {
    ConfigurationBuilder cb = new ConfigurationBuilder();
    cb.persistence()
      .passivation(false)
      .addStore(RedisCacheStoreConfigurationBuilder.class)
      .ignoreModifications(false)
      .fetchPersistentState(false)
      .purgeOnStartup(false)
      .preload(false)
      .shared(true)
      .addProperty("host", System.getenv("REDIS_HOST"))
      .addProperty("port", System.getenv("REDIS_PORT"))
      .addProperty("database", String.valueOf(database));

    return cb.build();
  }
Run Code Online (Sandbox Code Playgroud)

RedisCacheStoreConfigurationBuilder你看到有基本上是原有门店的精简版本,但我不需要哨兵或服务器模式,我只是想连接到主机,端口和数据库。

然后我基本上复制了org.keycloak.models.sessions.infinispan删除与删除缓存相关的所有内容,而不是通常使用没有装饰器的缓存来跳过缓存存储。

如果我能帮上什么忙,请告诉我,我会准备一篇更详细地说明如何做到这一点的帖子,还包括一个包含我正在谈论的代码的存储库。如果有人还在尝试这个,请让我知道更多。


Gal*_*eño 1

在 Infinispan 背后使用 Redis 存储有什么特殊原因吗?

更简单的解决方案可能是将持久性配置为文件或共享数据库。对于这样的缓存用例,基于文件的持久性可能就足够了。请参阅此处有关使用基于文件的持久性配置 Infinispan 的示例。或者,您可以存储到共享数据库,例如 Postgresql,但这需要更多设置(例如参见参考卡)。