在 Keycloak 26 中存储会话

2024 年 12 月 17 日,作者:Michal Hajas

Keycloak 26 现在默认使用持久用户会话功能。在这篇博文中,我们将揭示我们引入此功能的背景原因、有哪些替代方案以及未来发展方向。

Keycloak 26 会话存储速查表

本节提供关于会话存储类型以及在 Keycloak 26 中何时应使用它们的 TLDR 指南。以下各节将详细介绍每种存储类型以及引入或放弃每种存储类型的理由。

站点数量 会话存储 特性 何时使用 启用 Keycloak CLI 选项

单站点

持久会话

  • 会话存储在数据库中并在内存中缓存

  • 集群重启后会话仍然可用

  • 更低的内存使用量

  • 更高的数据库使用量

  • 标准安装的默认和推荐配置

  • 您希望会话在重启和升级后仍然存在

  • 接受更高的数据库使用量

无需额外配置

会话存储在内存中

  • 更快的读写速度

  • 集群重启后会话丢失

  • 更高的内存使用量(所有会话必须在内存中)

  • 无法使用持久用户会话功能

  • 请在此处提供您的反馈 here,因为我们想了解您为什么不能使用持久用户会话

--features-disabled="persistent-user-sessions"

会话存储在外部 Infinispan 中

  • 会话仅存储在外部 Infinispan 中

  • 降低数据库使用量

  • 使用 Hot Rod 客户端与外部 Infinispan 通信

  • 实验性功能

  • 请勿在生产环境中使用,因为它还是实验性的

  • 如果您对此功能感兴趣并希望帮助使其得到支持,请在此处评估并提供您的反馈 here

--features="clusterless"
--features-disabled="persistent-user-sessions"

会话存储在内存和外部 Infinispan 中

  • 每个会话的 4 个副本,Keycloak 内存中 2 个,Infinispan 内存中 2 个

  • Keycloak 集群重启后会话仍然可用

  • 高内存使用量

  • 实验性的,很快将被移除

  • 当您在以前的版本中使用此设置,而现在无法切换到持久用户会话时

--features="cache-embedded-remote-store"
--features-disabled="persistent-user-sessions"

多站点 (指南)

持久用户会话

  • 会话存储在数据库中,不在 Keycloak 内存中缓存

  • 同步地将会话复制到第二个站点(取决于数据库配置)

  • 当需要应对整个站点中断的弹性时

--features="multi-site"

会话存储在外部 Infinispan 中

  • 会话仅存储在外部 Infinispan 中

  • 使用 Hot Rod 客户端与外部 Infinispan 通信

  • 降低数据库使用量

  • 实验性功能

  • 请勿在生产环境中使用,因为它还是实验性的

  • 如果您对此功能感兴趣并希望帮助使其得到支持,请在此处评估并提供您的反馈 here

--features="multi-site,clusterless"
--features-disabled="persistent-user-sessions"

会话存储的演变

在早期的 Keycloak 版本中,所有会话都只存储在嵌入式 Infinispan 中 - 分布式缓存中每个 Keycloak 节点的内存中(每个 Keycloak 节点存储一部分会话,每个会话至少存在于 2 个节点中)。这在会话数量较少到中等的单站点环境中运行良好,并且该设置能够抵抗一个 Keycloak 节点故障而不会丢失任何数据。如果我们增加存储每个会话的节点数量,则可以扩展到多个节点。

如果发生整个站点灾难怎么办?

当更多节点发生故障或整个站点发生故障时,问题就出现了。用户要求更具弹性的设置。为此,我们引入了跨站点功能的预览版。对会话数据的影响是我们将其复制到 4 个位置 - 2 个 Keycloak 集群和 2 个 Infinispan 集群。这些位置中的每一个都需要存储所有会话,以便能够搜索/查询它们。

最初,此设置的性能不是很好,其中一个原因是我们需要同步复制数据 4 次以保持系统处于正确的状态。由于这种糟糕的性能,我们最初想要放弃该功能,但是由于社区的强烈兴趣,我们决定改进该功能。经过多次优化和性能调整,我们能够在 Keycloak 24 中以 multi-site 的名称发布此功能,该功能允许主-备设置。此架构将一些数据异步复制到第二个 Keycloak 集群,因此,我们无法以主-主方式使用此设置。

我希望我的会话能够幸存下来!

即使通过此设置我们更具弹性,但当整个部署崩溃时,我们仍然会丢失会话,例如在更新期间。我们收到了很多关于此问题的投诉。

这就是持久会话作为解决这两个问题的救星而出现的原因 - 异步更新复制到另一个站点和会话丢失。其想法是将会话存储在数据库中 - 会话的真实来源。我们已经将离线会话存储在数据库中,因此我们重用了这个概念,并引入了一个名为持久用户会话的新功能,该功能现在在 Keycloak 26 中默认启用。

数据库是存储这种写密集型对象的正确位置吗?

几乎每个进入 Keycloak 的请求都需要检查会话是否存在、是否有效,并且通常还需要更新其有效期限。这使得会话成为读写密集型对象,数据库是否是存储它们的正确位置这个问题是合理的。

在撰写这篇博文时,我们没有收到任何报告表明持久用户会话存在性能问题,而且看起来优点克服了缺点。尽管如此,我们还有一个实验模式下的附加功能供您评估。如上所述,Keycloak 24 中多站点设置的一些问题是我们需要将会话复制到 4 个位置,并且第二个 Keycloak 集群异步接收一些更新。这也可以通过仅将会议存储在外部 Infinispan 中来解决,因为会话仅复制两次而不是四次。此外,由于我们不需要将更改复制到 Keycloak 节点,因此不再使用异步复制。Infinispan 还为搜索会话提供了查询和索引功能,避免了存储在嵌入式 Infinispan 中的会话所需的顺序扫描。请注意,这是一个实验性功能,因此尚未完全完成和性能优化。我们渴望听到您的反馈,以了解持久用户会话在哪些方面失败,以及纯 Infinispan 会话存储可以在哪些方面发挥作用。

我有哪些选项,我应该考虑哪些选项?

由于我们无法在没有适当弃用期的情况下从上面的列表中删除任何选项,因此所有选项仍然可以在 Keycloak 26 中使用,但是,其中一些选项比其他选项更受青睐。

单站点,会话存储在数据库中并在内存中缓存

这是 Keycloak 26 中的默认设置。

单站点,会话存储在内存中

这是 Keycloak 26 之前版本中使用的默认设置,目前可能是所有设置中最常用的。建议切换到持久用户会话,并且在 Keycloak 26 中无需额外配置即可自动完成切换。但是,如果您在使用持久用户会话时遇到一些问题(渴望在此处听到您的反馈 here),并且您不介意在重启时丢失会话,则可以通过禁用 persistent-user-sessions 功能来启用此设置。

bin/kc.[sh|bat] build --features-disabled="persistent-user-sessions"

单站点,会话存储在外部 Infinispan 中

这是上面提到的实验性设置。要配置此项,请禁用 persistent-user-sessions 并启用 clusterless 功能。

bin/kc.[sh|bat] build --features="clusterless" --features-disabled="persistent-user-sessions"

单站点,会话存储在内存和外部 Infinispan 中

此设置使用旨在用于多站点的功能,但是,这也经常在单站点中使用,因为它具有在 Keycloak 重启时不会丢失会话的优点。我们认为持久用户会话使此设置过时,Keycloak 将拒绝使用此设置启动并显示此消息:Remote stores are not supported for embedded caches….。此功能已弃用,将在下一个 Keycloak 主要版本中删除。要运行此配置,请禁用 persistent-user-sessions,启用 cache-embedded-remote-store 功能并相应地配置嵌入式 Infinispan。

bin/kc.[sh|bat] build --features="cache-embedded-remote-store" --features-disabled="persistent-user-sessions"

多站点的选项

在多站点中运行 Keycloak 需要两个构建块,以使数据在两个站点中可用和同步。同步复制的数据库和每个站点中的外部 Infinispan,并启用跨站点复制。整个设置在此处描述 here。从存储会话的角度来看,该设置始终强制使用持久用户会话功能,并且会话仅存储在数据库中,而不在 Keycloak 的内存中缓存。要配置此项,请启用 multi-site 功能。

bin/kc.[sh|bat] build --features="multi-site"

也可以评估为单站点描述的实验性 clusterless 功能在多站点中的应用。在此设置中,会话不存储在数据库中,而是存储在外部 Infinispan 中。请注意,这是一个实验性功能,因此尚未完全记录和性能优化。要配置此项,请禁用 persistent-user-sessions 并启用 multi-siteclusterless 功能。

bin/kc.[sh|bat] build --features="multi-site,clusterless" --features-disabled="persistent-user-sessions"

欢迎反馈

常见问题

为什么在具有持久用户会话的多站点设置中我们需要外部 Infinispan

在这种情况下,外部 Infinispan 不用于存储会话,但是,我们仍然需要它用于两个 Keycloak 站点之间的通信,例如,用于失效消息、用于后台任务的同步以及用于存储某些对象(通常是短期的对象),例如身份验证会话、登录失败或操作令牌。