Pooling Support

池化 LDAP 连接有助于减轻为每次 LDAP 交互创建新的 LDAP 连接带来的开销。虽然 Java LDAP pooling support 存在,但它在其配置选项和功能方面受到限制,例如连接验证和池维护。Spring LDAP 提供了对每个 ContextSource 详细池配置的支持。 通过在应用程序上下文配置中为 <ldap:context-source /> 元素提供 <ldap:pooling /> 子元素的方式提供了池化支持。只读和读写 DirContext 对象将被单独池化(如果指定了 anonymous-read-only)。 Jakarta Commons-Pool 用于提供底层池实现。

DirContext Validation

与 JDK 提供的 LDAP 池化功能相比,池化连接验证是使用自定义池化库的主要动机。验证允许检查池化 DirContext 连接,以确保在从池中检出连接、将连接检入池,或者连接处于池空闲状态时,这些连接仍然正确连接和配置。

如果配置了连接验证,则会使用 DefaultDirContextValidator 来验证池连接。 DefaultDirContextValidator 会执行一个 DirContext.search(String, String, SearchControls),其中名称为空、过滤器为 "objectclass=*"、且 SearchControls 被设置为用仅包含 objectclass 特性和 500ms 超时的单个结果作为限制。如果返回的 NamingEnumeration 中有结果,则 DirContext 将通过验证。如果没有返回结果或抛出异常,则 DirContext 将验证失败。对于大多数 LDAP 服务器,默认设置应该不需要进行任何配置更改,并且提供最快的验证 DirContext 的方式。如果你需要自定义,可以使用 Pool Configuration 中描述的验证配置属性。

如果连接抛出被认为是非暂态的异常,则自动使该连接无效。例如,如果 DirContext 实例抛出 javax.naming.CommunicationException,则将其解释为非暂态错误,并且自动使该实例无效,而不会产生其他 testOnReturn 操作的开销。解释为非暂态的异常是通过使用 PoolingContextSourcenonTransientExceptions 属性进行配置的。

Pool Configuration

<ldap:pooling /> 元素上提供了以下属性用于 DirContext 池的配置:

Table 1. Pooling Configuration Attributes
Attribute Default Description

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 Configuration

<ldap:pooling2 /> 元素上提供了以下属性用于配置 DirContext 池:

Table 2. Pooling Configuration Attributes
Attribute Default Description

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 操作的情况下自动失效。

Configuration

配置池化需要在 <ldap:context-source> 元素中添加一个嵌套的 <ldap:pooling> 元素,如下所示:

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

在实际情况中,您可能需要配置池选项并启用连接验证。之前的示例展示了这个基本思想。

Validation Configuration

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

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

Known Issues

本节介绍在人们使用 Spring LDAP 时有时会遇到的问题。目前,它涵盖以下问题:

Custom Authentication

PoolingContextSource 假设从 ContextSource.getReadOnlyContext() 检索的所有 DirContext 对象都具有相同环境,同样地,从 ContextSource.getReadWriteContext() 检索的所有 DirContext 对象也具有相同环境。这意味着使用 AuthenticationSource 配置的 LdapContextSource 封装在一个 PoolingContextSource 中不能按预期功能。池将使用第一个用户的凭据填充,除非需要新的连接,否则后续上下文请求将不会针对请求线程的 AuthenticationSource 指定的用户进行填充。