設定執行緒池的概念

了解這些概念以避免資源耗盡和壅塞

本節旨在協助您了解如何為 Keycloak 設定執行緒池和連線池的考量事項與最佳實務。如需套用此設定的範例,請參閱使用 Keycloak Operator 部署 Keycloak 以實現高可用性

概念

Quarkus 執行器池

Keycloak 的請求以及阻塞探測都由執行器池處理。根據可用的 CPU 核心數,其最大執行緒數為 50 個或更多。執行緒會視需要建立,並在不再需要時結束,因此系統會自動擴展和縮減。Keycloak 允許透過 http-pool-max-threads 設定選項來配置最大執行緒池大小。請參閱使用 Keycloak Operator 部署 Keycloak 以實現高可用性以取得範例。

在 Kubernetes 上執行時,請調整工作執行緒的數量,以避免產生超出 Pod 的 CPU 限制所允許的負載,從而避免節流,這會導致壅塞。在實體機器上執行時,請調整工作執行緒的數量,以避免產生超出節點可處理的負載,從而避免壅塞。壅塞會導致更長的響應時間和增加的記憶體使用量,最終導致系統不穩定。

理想情況下,您應該從較低的執行緒限制開始,並根據目標輸送量和響應時間進行調整。當負載和執行緒數量增加時,資料庫連線也可能成為瓶頸。一旦請求無法在 5 秒內取得資料庫連線,它將會失敗並在日誌中顯示類似無法取得 JDBC 連線的訊息。呼叫者將收到一個 HTTP 5xx 狀態碼的響應,表示伺服器端錯誤。

如果您將資料庫連線數和執行緒數增加太多,系統在高負載下會因請求排隊而壅塞,這會導致效能不佳。資料庫連線數分別透過Database 設定中的 db-pool-initial-sizedb-pool-min-sizedb-pool-max-size 來配置。較小的數值可確保所有客戶端都有快速的響應時間,即使在負載高峰時偶爾會有請求失敗。

JGroups 連線池

這目前僅適用於單站點設定。在具有外部 Infinispan 的多站點設定中,這不再是限制。

叢集中所有 Keycloak 節點中的執行器執行緒總數不應超過 JGroups 執行緒池中可用的執行緒數,以避免錯誤org.jgroups.util.ThreadPool: thread pool is full。要第一次看到錯誤,系統屬性 jgroups.thread_dumps_threshold 需要設定為 1,否則訊息只會在 10000 個請求被拒絕後才會出現。

JGroup 執行緒的數量預設為 200。雖然可以使用 Java 系統屬性 jgroups.thread_pool.max_threads 進行配置,但我們建議保持此值。如實驗所示,叢集中 Quarkus 工作執行緒的總數不得超過每個節點中 JGroup 執行緒池的 200 個執行緒,以避免 JGroups 通訊中的死鎖。假設一個 Keycloak 叢集有四個 Pod,則每個 Pod 應有 50 個 Quarkus 工作執行緒。使用 Keycloak 設定選項 http-pool-max-threads 來配置 Quarkus 工作執行緒的最大數量。

使用指標來監控池中的 JGroup 執行緒總數以及池中活動的執行緒。當使用 TCP 作為 JGroups 傳輸協定時,指標 vendor_jgroups_tcp_get_thread_pool_sizevendor_jgroups_tcp_get_thread_pool_size_active 可用於監控。當使用 UDP 時,可以使用指標 vendor_jgroups_udp_get_thread_pool_sizevendor_jgroups_udp_get_thread_pool_size_active。這對於監控限制 Quarkus 執行緒池大小,以保持活動 JGroup 執行緒的數量低於最大 JGroup 執行緒池大小很有用。

負載釋放

預設情況下,即使請求處理停滯,Keycloak 也會無限期地將所有傳入的請求排隊。這將在 Pod 中使用額外的記憶體,可能會耗盡負載平衡器中的資源,並且請求最終將在客戶端超時,而客戶端不知道請求是否已處理。要限制 Keycloak 中排隊的請求數量,請設定一個額外的 Quarkus 設定選項。

設定 http-max-queued-requests 以指定最大佇列長度,以便在超過此佇列大小後允許有效的負載釋放。假設一個 Keycloak Pod 每秒處理約 200 個請求,1000 個請求的佇列將導致最長等待時間約為 5 秒。

當此設定處於活動狀態時,超過排隊請求數量的請求將返回 HTTP 503 錯誤。Keycloak 將錯誤訊息記錄在其日誌中。

探測

Keycloak 的存活性探測是非阻塞的,以避免在高負載下重新啟動 Pod。

整體健康狀況探測和就緒性探測在某些情況下可能會阻塞以檢查與資料庫的連線,因此它們可能在高負載下失敗。因此,Pod 可能在高負載下變為未就緒狀態。

OS 資源

為了使 Java 能夠建立執行緒,在 Linux 上執行時需要有可用的檔案控制代碼。因此,開啟檔案的數量(如在 Linux 上以 ulimit -n 檢索)需要為 Keycloak 提供額外的空間以增加所需的執行緒數量。每個執行緒還會消耗記憶體,並且容器記憶體限制需要設定為允許此值的值,否則 Pod 將被 Kubernetes 殺死。

本頁內容