連線池支援

LDAP 連線池有助於減輕每次 LDAP 互動建立新連線的開銷。雖然 Java LDAP 連線池支援 已經存在,但其配置選項和功能有限,例如連線驗證和連線池維護。Spring LDAP 支援基於每個 ContextSource 進行詳細的連線池配置。

透過在應用上下文配置中的 <ldap:context-source /> 元素中提供一個 <ldap:pooling /> 子元素來提供連線池支援。只讀和讀寫 DirContext 物件會分開進行連線池管理(如果指定了 anonymous-read-only)。Jakarta Commons-Pool 被用來提供底層連線池實現。

DirContext 驗證

相較於 JDK 提供的 LDAP 連線池功能,使用自定義連線池庫的主要動機是能夠對連線池中的連線進行驗證。驗證允許檢查連線池中的 DirContext 連線,以確保它們在從連線池中取出、放回連線池或在連線池中空閒時仍保持正確連線和配置。

如果配置了連線驗證,將使用 DefaultDirContextValidator 來驗證連線池中的連線。DefaultDirContextValidator 執行一個 DirContext.search(String, String, SearchControls) 操作,使用空名稱、過濾器 "objectclass=*",並將 SearchControls 設定為只返回一個結果,僅包含 objectclass 屬性,超時時間為 500ms。如果返回的 NamingEnumeration 有結果,則 DirContext 透過驗證。如果沒有返回結果或丟擲異常,則 DirContext 驗證失敗。預設設定適用於大多數 LDAP 伺服器,無需配置更改,並提供了驗證 DirContext 的最快方法。如果需要自定義,可以使用 連線池配置 中描述的驗證配置屬性進行設定。

如果連線丟擲被視為非瞬時(non-transient)的異常,它們會自動失效。例如,如果一個 DirContext 例項丟擲 javax.naming.CommunicationException,它會被解釋為非瞬時錯誤,並且該例項會自動失效,而無需額外的 testOnReturn 操作開銷。哪些異常被解釋為非瞬時異常是透過 PoolingContextSourcenonTransientExceptions 屬性配置的。

連線池配置

<ldap:pooling /> 元素上提供了以下屬性,用於配置 DirContext 連線池

表 1. 連線池配置屬性
屬性 預設值 描述

max-active

8

同時可以從該連線池中分配的每種型別(只讀或讀寫)的最大活動連線數。可以使用非正數表示無限制。

max-total

-1

同時可以從該連線池中分配的所有型別(只讀和讀寫總計)的最大活動連線總數。可以使用非正數表示無限制。

max-idle

8

每種型別(只讀或讀寫)在連線池中可以保持空閒的最大活動連線數,超過此數量時,額外的連線將被釋放。可以使用非正數表示無限制。

min-idle

0

每種型別(只讀或讀寫)在連線池中可以保持空閒的最小活動連線數,低於此數量時,將建立額外的連線。可以使用零(預設值)表示不建立。

max-wait

-1

當沒有可用連線時,連線池等待連線返回的最大毫秒數,超過此時間將丟擲異常。可以使用非正數表示無限期等待。

when-exhausted

BLOCK

指定當連線池耗盡時的行為。

  • FAIL 選項在連線池耗盡時丟擲 NoSuchElementException

  • BLOCK 選項會等待直到有新物件可用。如果 max-wait 為正數,並且在 max-wait 時間過期後沒有新物件可用,將丟擲 NoSuchElementException

  • GROW 選項會建立一個並返回一個新的物件(這基本上使得 max-active 變得沒有意義)。

test-on-borrow

false

從連線池中借用物件之前是否進行驗證。如果物件驗證失敗,它將從連線池中移除,然後嘗試借用另一個物件。

test-on-return

false

將物件返回到連線池之前是否進行驗證。

test-while-idle

false

物件是否由空閒物件驅逐器(如果存在)進行驗證。如果物件驗證失敗,它將從連線池中移除。

eviction-run-interval-millis

-1

空閒物件驅逐器執行緒每次執行之間的休眠毫秒數。非正數表示不執行空閒物件驅逐器執行緒。

tests-per-eviction-run

3

空閒物件驅逐器執行緒每次執行時(如果存在)檢查的物件數量。

min-evictable-time-millis

1000 * 60 * 30 (30 分鐘)

物件在連線池中保持空閒的最短時間,超過此時間後,空閒物件驅逐器(如果存在)才有資格將其驅逐。

validation-query-base

LdapUtils.emptyName()

驗證連線時使用的搜尋基礎。僅在指定 test-on-borrow, test-on-returntest-while-idle 時使用。

validation-query-filter

objectclass=*

驗證連線時使用的搜尋過濾器。僅在指定 test-on-borrow, test-on-returntest-while-idle 時使用。

validation-query-search-controls-ref

null;預設搜尋控制設定如上所述。

驗證連線時使用的 SearchControls 例項的 ID。僅在指定 test-on-borrow, test-on-returntest-while-idle 時使用。

non-transient-exceptions

javax.naming.CommunicationException

以逗號分隔的 Exception 類列表。列出的異常在立即失效方面被視為非瞬時異常。如果對連線池中的 DirContext 例項的呼叫丟擲列出的任何異常(或其子類),該物件將自動失效,無需額外的 testOnReturn 操作。

Pool2 配置

<ldap:pooling2 /> 元素上提供了以下屬性,用於配置 DirContext 連線池

表 2. 連線池配置屬性
屬性 預設值 描述

max-total

-1

同時可以從該連線池中分配的所有型別(只讀和讀寫總計)的最大活動連線總數。可以使用非正數表示無限制。

max-total-per-key

8

連線池按鍵(key)分配的物件例項數量限制(已借出或空閒)。達到限制時,子池耗盡。負值表示無限制。

max-idle-per-key

8

每種型別(只讀或讀寫)在連線池中可以保持空閒的最大活動連線數,超過此數量時,額外的連線將被釋放。負值表示無限制。

min-idle-per-key

0

每種型別(只讀或讀寫)在連線池中可以保持空閒的最小活動連線數,低於此數量時,將建立額外的連線。可以使用零(預設值)表示不建立。

max-wait

-1

當沒有可用連線時,連線池等待連線返回的最大毫秒數,超過此時間將丟擲異常。可以使用非正數表示無限期等待。

block-when-exhausted

true

是否等待直到有新物件可用。如果 max-wait 為正數,並且在 maxWait 時間過期後沒有新物件可用,將丟擲 NoSuchElementException

test-on-create

false

在借用物件之前是否進行驗證。如果物件驗證失敗,則借用失敗。

test-on-borrow

false

從連線池中借用物件之前是否進行驗證的指示器。如果物件驗證失敗,它將從連線池中移除,然後嘗試借用另一個物件。

test-on-return

false

將物件返回到連線池之前是否進行驗證的指示器。

test-while-idle

false

物件是否由空閒物件驅逐器(如果存在)進行驗證的指示器。如果物件驗證失敗,它將從連線池中移除。

eviction-run-interval-millis

-1

空閒物件驅逐器執行緒每次執行之間的休眠毫秒數。非正數表示不執行空閒物件驅逐器執行緒。

tests-per-eviction-run

3

空閒物件驅逐器執行緒每次執行時(如果存在)檢查的物件數量。

min-evictable-time-millis

1000 * 60 * 30 (30 分鐘)

物件在連線池中保持空閒的最短時間,超過此時間後,空閒物件驅逐器(如果存在)才有資格將其驅逐。

soft-min-evictable-time-millis

-1

物件在連線池中保持空閒的最短時間,超過此時間後,空閒物件驅逐器才有資格將其驅逐,但附加條件是每個鍵(key)至少保留最小數量的物件例項。如果 min-evictable-time-millis 設定為正值,則此設定將被覆蓋。

eviction-policy-class

org.apache.commons.pool2.impl.DefaultEvictionPolicy

此連線池使用的驅逐策略實現。連線池嘗試使用執行緒上下文類載入器載入該類。如果失敗,連線池將嘗試使用載入此類的類載入器載入該類。

fairness

false

連線池公平地服務等待借用連線的執行緒。true 意味著等待執行緒按照 FIFO(先進先出)佇列的方式服務。

jmx-enable

true

為連線池啟用了平臺 MBean 伺服器的 JMX。

jmx-name-base

null

用作 JMX 啟用連線池名稱一部分的 JMX 名稱基礎。

jmx-name-prefix

pool

用作 JMX 啟用連線池名稱一部分的 JMX 名稱字首。

lifo

true

指示連線池對空閒物件是否具有 LIFO(後進先出)行為或作為 FIFO(先進先出)佇列。LIFO 總是返回連線池中最近使用的物件,而 FIFO 總是返回空閒物件池中最舊的物件。

validation-query-base

LdapUtils.emptyPath()

用於驗證搜尋的基礎 DN。

validation-query-filter

objectclass=*

用於驗證查詢的過濾器。

validation-query-search-controls-ref

null;預設搜尋控制設定如上所述。

驗證連線時使用的 SearchControls 例項的 ID。僅在指定 test-on-borrow, test-on-returntest-while-idle 時使用

non-transient-exceptions

javax.naming.CommunicationException

以逗號分隔的 Exception 類列表。列出的異常在立即失效方面被視為非瞬時異常。如果對連線池中的 DirContext 例項的呼叫丟擲列出的任何異常(或其子類),該物件將自動失效,無需額外的 testOnReturn 操作。

配置

配置連線池需要在 <ldap:context-source> 元素中巢狀新增一個 <ldap:pooling> 元素,如下所示

<beans>
   ...
    <ldap:context-source
        password="secret" url="ldap://:389" username="cn=Manager">
        <ldap:pooling />
    </ldap:context-source>
   ...
</beans>

在實際情況中,你可能會配置連線池選項並啟用連線驗證。上面的示例展示了基本思路。

驗證配置

以下示例在將每個 DirContext 傳遞給客戶端應用之前對其進行測試,並測試在連線池中處於空閒狀態的 DirContext 物件

<beans>
   ...
    <ldap:context-source
        username="cn=Manager" password="secret" url="ldap://:389" >
        <ldap:pooling
            test-on-borrow="true"
            test-while-idle="true" />
    </ldap:context-source>
   ...
</beans>

已知問題

本節描述了人們在使用 Spring LDAP 時有時會遇到的問題。目前,它涵蓋了以下問題

自定義認證

PoolingContextSource 假定從 ContextSource.getReadOnlyContext() 獲取的所有 DirContext 物件都具有相同的環境,同樣地,從 ContextSource.getReadWriteContext() 獲取的所有 DirContext 物件也具有相同的環境。這意味著將配置了 AuthenticationSourceLdapContextSource 包裝到 PoolingContextSource 中時,其行為不會按預期進行。連線池將使用第一個使用者的憑據填充,並且除非需要新的連線,否則後續的上下文請求將不會為請求執行緒指定的 AuthenticationSource 使用者填充。