bin/kc.[sh|bat] [start-dev|build|start] --features="persistent-user-sessions"
2024 年 6 月 12 日,作者:Alexander Schwartz
先前版本的 Keycloak 仅在内存中存储常规用户会话(也称为在线用户会话)。因此,当您关闭或重启 Keycloak 集群时,所有用户都将被登出。
在 Keycloak 25 中,有一个预览功能“持久用户会话”,它将用户会话存储在其数据库中。如果在内存中找不到会话,则会从数据库加载,用户可以继续使用他们的会话,而无需重新身份验证。
此预览功能默认禁用,您需要使用 persistent-user-sessions 功能标志启用它才能试用。
您可以通过在此 GitHub 讨论帖中提供反馈来帮助使此功能得到完全支持。在 6 月 24 日,我们计划举办一个关于持久会话的“有问必答”环节。
启用此功能后,Keycloak 的内存使用量可能会减少,而数据库使用量可能会增加。
如果在 Keycloak 的缓存配置 XML 文件中未配置其他最大大小,则 Keycloak 将默认为 sessions、clientSessions、offlineSessions 和 offlineClientSessions 这些缓存中的每一个设置最大 10,000 个条目。如果您想在内存中保留更多会话,请参阅配置分布式缓存,了解如何配置不同的大小。
选项 spi-user-sessions-infinispan-offline-session-cache-entry-lifespan-override
和 spi-user-sessions-infinispan-offline-client-session-cache-entry-lifespan-override
将被忽略,因为将改为使用最大条目大小。
外部 Infinispan 实例支持 Keycloak 的多站点设置。如果您使用此类设置并启用了持久用户会话,则可以(并且应该)设置要在外部 Infinispan 中保留的最大会话数,以限制外部 Infinispan 的内存消耗。请参阅 Infinispan 关于如何在 Infinispan 缓存中配置驱逐的文档。
如果并发用户会话数超过 Keycloak 中的最大缓存大小,您将看到数据库活动增加,以便在例如令牌刷新或调用用户信息端点时从数据库加载会话。这些请求也会导致延迟增加,具体取决于数据库对这些读取语句的响应时间。监控缓存命中率,以查看您的设置是否需要优化。
对于每次登录、令牌刷新和注销,数据库中的会话表都会更新,并将显示为数据库活动增加。Keycloak 尝试将并发会话更新捆绑到单个事务中,但数据库的 CPU 和 IOPS 利用率仍将显着增加。这些请求也会导致延迟增加,具体取决于数据库对这些写入语句的响应时间。
对您环境的影响将取决于您的基础设施和使用模式。作为参考指标,我们使用以下设置运行了一项测试
每秒 150 次登录和 150 次注销
Aurora PostgreSQL 区域数据库 15.5
类型 db.t4g.large 服务器(2 个 ARM vCPU 核心,8 GB RAM)
我们观察到运行时指标的以下变化
在数据库方面
每秒额外 300 次提交
CPU 使用率增加 1 到 1.5 个 CPU 核心,具体取决于并发会话数
大约额外 2500 个 WriteIOPS
在 Keycloak 方面
Keycloak 上的 CPU 使用率保持恒定
创建 10,000 个会话后,内存使用率保持恒定
对于单可用区数据库,登录和注销的第 50 百分位响应时间分别增加了 20 毫秒和 10 毫秒;对于双可用区数据库,则分别增加了 30 毫秒和 20 毫秒。
我们建议您为您的环境运行基准测试。使用我们在 Keycloak Benchmark Project 中提供的工具作为工具箱。
请参阅启用 Keycloak 指标,了解如何为 Keycloak 启用指标以监控有关您的缓存和 HTTP 响应时间的信息。
社区过去一直在评估不同的配置,其中一些配置存在缺点,并且未获得 Keycloak 的官方支持。启用持久会话后,现在可以简化这些设置。
使用具有非常大的 JVM 堆大小的部署:过去,需要大量 JVM 内存来将所有会话保存在内存中,并避免内存不足的情况。由于持久会话存储在数据库中,并且仅在内存中保留一个子集用于缓存,因此您现在可以减少分配给 Keycloak 实例的内存。
一种流行的方法是使用离线会话来保持用户登录状态,因为即使在此之前,这些会话也已持久保存在数据库中。但是,离线会话的用途不同:其预期用途是允许应用程序代表用户访问资源,即使该用户已注销,并且常规在线会话注销也不会注销这些会话。启用持久用户会话后,您应该开始使用在线会话。现有的离线会话仍然可以使用,并且最终会过期。
在此设置中,嵌入式 Infinispan 将会话存储到数据库和自定义创建的表中。虽然这是登录和注销的默认设置,但只有在启动时加载所有会话时才会这样做,因为非持久用户会话的代码假定所有会话都位于内存中。所有会话都需要在启动时加载,否则客户端或 realm 的会话列表将不完整,并且无法保证例如给定用户只有一个会话的约束。借助 Keycloak 25 中的持久会话预览功能,这种新方法降低了设置的复杂性,并减少了 Keycloak 和 Infinispan 的内存占用。请参阅下文,了解如何迁移现有会话。
在此设置中,Keycloak 将读取会话并将其写入外部 Infinispan。与上述情况类似,所有会话都需要在启动时加载到嵌入式 Infinispan 和外部 Infinispan 中,否则客户端或 realm 的会话列表将不完整,并且无法保证例如给定用户只有一个会话的约束。从 Keycloak 24 开始,此类设置仅支持多站点设置。借助 Keycloak 25 中的持久会话预览功能,这种新方法降低了设置的复杂性,并减少了 Keycloak 的内存占用,并且无需运行外部 Infinispan。请参阅下文,了解如何迁移现有会话。
如果您一直在使用连接到嵌入式 Infinispan 的 JDBC 存储,或外部 Infinispan 在 Keycloak 24 中存储 Keycloak 在线会话,则当您首次启动 Keycloak 25 时启用持久用户会话(当且仅当启用时),您可以迁移这些会话。
迁移完成后,您应该删除嵌入式会话缓存的任何 JDBC 持久性配置。如果您在单站点设置中使用过外部 Infinispan,您还应该删除与外部 Infinispan 的连接。
由于这是一个预览功能,因此默认情况下未启用。一旦我们认为此功能已完全支持,我们计划在未来的版本中默认启用它。
如果您已迁移到 Keycloak 25,我们建议您清除设置中的所有现有在线用户会话。
根据您是在开发环境中使用它、构建 Keycloak 发行版,还是依赖于启动时自动重建 Keycloak,您的命令将如下所示
bin/kc.[sh|bat] [start-dev|build|start] --features="persistent-user-sessions"
如果您使用环境变量来设置选项,请设置以下环境变量,或者如果环境变量已存在,则添加该值。
KC_FEATURES=persistent-user-sessions
如果您使用 Keycloak Operator,请将其添加到 Keycloak CR 中启用的功能中
apiVersion: k8s.keycloak.org/v2alpha1 kind: Keycloak metadata: name: example-kc spec: features: enabled: - persistent-user-sessions ...
请参阅启用和禁用功能,了解有关如何启用功能的更多信息。
在我们努力使此功能获得完全支持的同时,我们也在开发类似的功能。其中一些功能将使 Keycloak 的部署更简单,而另一些功能最终将实现 Keycloak 多站点主动-主动设置。
加入这些功能的讨论,并为它们投赞成票,以便我们了解您对此感兴趣。
感谢 Keycloak 团队成员 Kamesh Akella、Michal Hajas、Pedro Ruivo、Anna Manukyan 和 Ryan Emerson,他们讨论了想法和边缘情况,贡献了代码并执行了中间拉取请求和版本的测试。特别感谢社区成员 Tristan971、daviddelannoy 和 Thomas Darimont,他们加入了 GitHub 讨论并提供了反馈。
您可以通过试用预览功能并在此 GitHub 讨论帖中提供反馈来帮助使此功能获得完全支持。
也可以使用此帖子询问有关持久用户会话的问题。在 6 月 24 日,我们计划举办一个关于持久会话的“有问必答”环节。