线程池配置概念

理解这些概念以避免资源耗尽和拥塞

本节旨在帮助您理解关于如何为 Keycloak 配置线程池连接池的注意事项和最佳实践。有关应用此配置的示例,请访问 使用 Keycloak Operator 部署 Keycloak 实现高可用性

概念

JGroups 通信

JGroups 通信,用于单站点设置中 Keycloak 节点之间的通信,得益于虚拟线程的使用,当 Keycloak 至少有两个核心可用时,虚拟线程在 OpenJDK 21 中可用。这减少了内存使用量,并消除了配置线程池大小的需求。因此,建议使用 OpenJDK 21。

Quarkus 执行器池

Keycloak 请求以及阻塞探针由执行器池处理。根据可用的 CPU 核心数,它最多可以有 50 个或更多线程。线程按需创建,并在不再需要时结束,因此系统将自动向上和向下扩展。Keycloak 允许通过 http-pool-max-threads 配置选项来配置最大线程池大小。有关示例,请参阅 使用 Keycloak Operator 部署 Keycloak 实现高可用性

在 Kubernetes 上运行时,调整工作线程数以避免创建超出 Pod 的 CPU 限制的负载,从而避免限制,这会导致拥塞。在物理机上运行时,调整工作线程数以避免创建超出节点处理能力的负载,从而避免拥塞。拥塞将导致更长的响应时间和增加的内存使用量,并最终导致系统不稳定。

理想情况下,您应该从较低的线程限制开始,并根据目标吞吐量和响应时间进行调整。当负载和线程数增加时,数据库连接也可能成为瓶颈。如果请求在 5 秒内无法获取数据库连接,则会失败并在日志中显示类似 Unable to acquire JDBC Connection 的消息。调用者将收到状态码为 5xx HTTP 的响应,指示服务器端错误。

如果您过度增加数据库连接数和线程数,系统在高负载下会因请求排队而变得拥塞,从而导致性能下降。数据库连接数分别通过 Database 设置 db-pool-initial-sizedb-pool-min-sizedb-pool-max-size 进行配置。较低的数值可确保所有客户端的快速响应时间,即使在负载高峰时偶尔出现请求失败。

负载分流

默认情况下,即使请求处理停滞,Keycloak 也会无限期地将所有传入请求排队。这将在 Pod 中使用额外的内存,可能会耗尽负载均衡器中的资源,并且请求最终会在客户端超时,而客户端不知道请求是否已被处理。要限制 Keycloak 中排队请求的数量,请设置一个额外的 Quarkus 配置选项。

配置 http-max-queued-requests 以指定最大队列长度,以便在超过此队列大小时进行有效的负载分流。假设 Keycloak Pod 每秒处理约 200 个请求,那么 1000 的队列将导致最长等待时间约为 5 秒。

当此设置激活时,超出排队请求数量的请求将返回 HTTP 503 错误。Keycloak 会在其日志中记录错误消息。

探针

Keycloak 的存活探针是非阻塞的,以避免在高负载下重启 Pod。

总体健康探针和就绪探针在某些情况下可能会阻塞以检查与数据库的连接,因此在高负载下可能会失败。因此,Pod 在高负载下可能会变为未就绪状态。

操作系统资源

为了使 Java 创建线程,在 Linux 上运行时,它需要有可用的文件句柄。因此,打开文件数(在 Linux 上通过 ulimit -n 检索)需要为 Keycloak 提供提前量,以增加所需的线程数。每个线程也会消耗内存,容器内存限制需要设置为允许此操作的值,否则 Pod 将被 Kubernetes 杀死。

本页内容