2023 年 12 月 18 日 作者:Alexander Schwartz,Kamesh Akella
对于客户身份和访问管理 (CIAM) 系统而言,高可用性至关重要,因为它所有系统(客户登录)的单一访问点。对于 Keycloak 23,提供了一份新的、更新的高可用性指南,描述了多站点设置。该指南包含详细的说明和针对云基础设施的蓝图,经测试,并可立即使用。
继续阅读以了解新功能,并窥视幕后,了解此设置是如何评估、测试和改进的。最后,我们将展望该功能何时不再是预览版。
Keycloak 多站点设置的最新更新标志着重大里程碑。Keycloak 23 包含一个观点指南,介绍如何在多站点配置中设置 Keycloak,包括用于云设置的蓝图。
该文档的高级主题是
在发布以上指南之前,我们开发了工具,使我们能够进行实验,并获得可重复的结果,用于性能、可扩展性和混沌测试我们的解决方案。
使用这些工具,我们首先测试了单站点设置,并在该设置正常工作后,也测试了多站点设置。
所有这些工具均以开源形式提供,我们邀请您审阅它们以提供反馈,并在您的环境中使用它们来运行您自己的性能基准测试和回归测试。
将此安装到测试环境中的 Keycloak 服务器中,并根据需要创建尽可能多的用户、客户端、组等,以运行您的性能基准测试。Keycloak 在其内部缓存中缓存大量信息,数据库也是如此,因此只有当您的数据库中有足够的数据时,您才能发现一些问题。
这包含可立即使用的场景,用于身份验证流程和 Keycloak 的管理 REST 端点。如果它还不适合您的需求,请将其用作库来创建您自己的基于现有步骤和自定义步骤的 Gatling 场景。这些测试以 JAR 和 shell 脚本包装器形式部署,因此您只需要在负载运行器上安装 Java,您就可以开始使用。
使用这些 Ansible 剧本启动一组 EC2 实例,以针对 Keycloak 测试安装驱动负载,并汇总结果。
基于 AWS 上的 Red Hat OpenShift 服务 (ROSA),使用脚本预配置监控、日志记录和有用的操作员来预配实例,准备部署 Keycloak。
在不同的区域或全局变体中设置 Aurora,并将其连接到 ROSA 环境。
这会部署 Keycloak,并附带额外的监控和调试工具,以便我们根据需要查看指标、日志和跟踪。
为主动-被动设置设置 Route 53,以将负载分发到两个不同 OpenShift 集群中的 Keycloak 部署。
我们每周都会使用 GitHub 操作、性能测试套件从头开始创建一个新的多 AZ 设置,并记录结果。这样,我们就可以在功能和性能回归出现时将其捕获。
感谢社区中已经尝试使用这些工具、发现错误并提交改进建议的所有人!
在使用上述工具时,我们能够重现 Keycloak 需要改进的几种情况。以下是 Keycloak 23 中针对单站点和多站点设置提供的改进
在高负载下运行 Keycloak 时,请求可能会在 Keycloak 实例中排队。排队的请求越多,回复请求所需的时间就越长。在以前的版本中,对存活性探测(/health/live
)的请求也会排队,探测最终会超时,然后 Kubernetes 会重新启动 Pod。在最新版本的 Keycloak 中,探测已重新实现为非阻塞,因此它不会排队,因此不会超时,并且 Pod 不会在高负载下重新启动。
当请求如上所述排队时,调用方将无法及时收到响应,并且 Pod 最终可能会耗尽资源,如内存或网络连接。建议的做法是在实例无法及时处理请求时尽早丢弃请求,这称为负载卸载。Keycloak 23 现在支持新选项 http-max-queued-requests
,它可以限制并发阻塞请求的数量。当超过该数量时,Keycloak 会立即返回响应 503 Server not Available
。这有两个好处:调用方会立即收到响应,并可以稍后重试,并且服务器端会立即释放资源。
当新的 Keycloak 实例启动或重新启动时,其缓存为空。如果在高负载下,针对 Keycloak 节点上的同一领域或同一客户端的并行请求到达,则以前版本的 Keycloak 会在每个并行请求中从数据库加载数据。这会导致数据库连接使用量激增,并导致初始响应延迟。当缓存或领域条目从缓存中逐出时,也会发生相同的情况,例如,因为它已被修改。最新版本的 Keycloak 会阻止这种情况,以便每个 Keycloak 实例只从数据库中获取一次数据,所有其他并行请求随后都会使用此数据,而不会再次查询数据库(请参阅#21521 和#22988,#24202)。
在集群中运行的 Keycloak 实例越多,并行处理的请求越多,JGroups 线程池上的负载就越高。JGroups 线程池确保 Keycloak 嵌入式 Infinispan 的通信顺畅,如果其容量超过,则会导致内部 Infinispan 通信超时。高可用性文档现在包含有关如何设置 Quarkus 线程池以不超过 JGroup 线程池的文档。
嵌入式 Infinispan 提供了改进的指标,允许您监控集群。Keycloak 指标端点公开的指标现在仅包含当前节点的 Infinispan 指标,因此如果另一个 Pod 当前正在启动或关闭,它们不会阻塞(ISPN-15042 和ISPN-15072)。这样,您就可以在这些关键时刻更好地了解集群情况。指标现在可以将缓存名称作为标签公开,因此可以通过在 Infinispan XML 配置中添加 <metrics names-as-tags="true" />
来更轻松地将其绘制在仪表板中。还提供针对站点之间延迟的其他指标。
我们彻底测试了 Infinispan 及其通信层 JGroups,并能够修复状态传输停止(ISPN-14982)或初始状态传输失败的情况。多站点设置中使用的 Gossip 路由器现在即使在负载均衡器具有多个 IP 地址的情况下也能正常工作(JGRP-2722,JGRP-2721,infinispan-operator#1857,以及infinispan-operator#1856)。
作为我们进行的测试的一部分,我们优化了 Keycloak,这些优化已内置到 Keycloak 中。它们无需额外的配置即可使用,除了 JGroup 线程池配置。虽然 Keycloak 在 Kubernetes 上的配置可能与生产环境非常相似,但我们预计数据库、网络、负载均衡器和安全强化在每个组织中都会有所不同,因此您需要根据自己的需求进行调整。
这就是我们选择将蓝图记录为文本的原因,这样您就可以了解我们做出的选择以及为什么不同的方面在一种设置中进行配置,而在其他设置中则使用其默认设置。
我们在 Keycloak 基准测试项目中使用的用于自动化设置的脚本侧重于高可用性,并将此与从工程角度易于调试和分析的配置相结合。生产环境中的设置将不具备该功能,因此我们不建议按原样使用这些脚本。不过,它们可以作为您自己的自动化的起点。
目前,我们正在针对主动/被动设置运行最终测试,并致力于使更多测试自动化。我们还在GitHub 上有关多站点设置的讨论中寻求社区的反馈:您喜欢这里的内容吗?是否缺少什么内容?您的反馈至关重要!
一旦我们的测试完成,并且我们收到社区的反馈,我们计划将其作为一项完全受支持的功能。这对社区来说是一个巨大的机会,可以参与到此设置中,在您的环境中尝试它,并分享您的发现。让我们共同构建一个更强大、更具弹性的 Keycloak!