池支持

池化 LDAP 连接有助于减轻为每次 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 属性和 500 毫秒超时。如果返回的 NamingEnumeration 有结果,则 DirContext 通过验证。如果没有返回结果或抛出异常,则 DirContext 验证失败。默认设置应该可以在大多数 LDAP 服务器上无需配置更改即可工作,并提供验证 DirContext 的最快方法。如果您需要自定义,可以使用 池配置 中描述的验证配置属性来执行此操作。

如果连接抛出被视为非瞬态的异常,则连接将自动失效。例如,如果 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-borrowtest-on-returntest-while-idle 时使用。

validation-query-filter

objectclass=*

验证连接时要使用的搜索过滤器。仅在指定 test-on-borrowtest-on-returntest-while-idle 时使用。

validation-query-search-controls-ref

null;默认搜索控制设置如上所述。

验证连接时要使用的 SearchControls 实例的 ID。仅在指定 test-on-borrowtest-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

池(检出或空闲)按键分配的对象实例数量限制。达到限制后,子池将耗尽。负值表示没有限制。

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

对象在池中处于空闲状态的最小时间,然后才能被空闲对象驱逐器驱逐,附加条件是每个键的最小对象实例数仍保留在池中。如果将此设置设置为正值,则将被 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-borrowtest-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://127.0.0.1:389" username="cn=Manager">
        <ldap:pooling />
    </ldap:context-source>
   ...
</beans>

在实际情况下,您可能会配置池选项并启用连接验证。前面的示例演示了总体思路。

验证配置

以下示例在将每个 DirContext 传递给客户端应用程序之前对其进行测试,并测试在池中处于空闲状态的 DirContext 对象

<beans>
   ...
    <ldap:context-source
        username="cn=Manager" password="secret" url="ldap://127.0.0.1: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 指定的用户填充后续上下文请求。