Pooling

Connection Creation部分描述了创建连接时的情况。它描述了几个Context实例如何共享同一连接。

LDAP 服务提供商支持的另一种连接共享类型称为连接池。在这种类型的共享中,LDAP 服务提供者维护(可能)以前使用的连接的池,并根据需要将它们分配给Context实例。当Context实例完成连接(关闭或垃圾回收)后,该连接将返回到池中以备将来使用。请注意,这种共享形式是 Sequences 的:从池中检索连接,使用连接,将其返回到池中,然后从池中再次为另一个Context实例检索连接。

每个 Java 运行时系统都会维护连接池。在某些情况下,连接池可以显着提高性能。例如,如果使用连接池,则只需要一个连接即可处理包含对同一 LDAP 服务器的四个引用引用的搜索响应。如果没有连接池,则这种情况将需要四个单独的连接。

本类的其余部分将更详细地描述如何使用连接池。

如何使用连接池

您可以通过将属性"com\.sun\.jndi\.ldap\.connect\.pool"添加到传递给初始上下文构造函数的环境属性中来请求连接池。这是an example

// Set up environment for creating initial context
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Enable connection pooling
env.put("com.sun.jndi.ldap.connect.pool", "true");

// Create one initial context (Get connection from pool)
DirContext ctx = new InitialDirContext(env);

// do something useful with ctx

// Close the context when we're done
ctx.close();   // Return connection to pool

// Create another initial context (Get connection from pool)
DirContext ctx2 = new InitialDirContext(env);

// do something useful with ctx2

// Close the context when we're done
ctx2.close();   // Return connection to pool

本示例连续创建两个初始上下文。第二个初始上下文将重用第一个初始上下文。要运行此程序并观察如何检索连接并将其返回到池,请使用以下命令行。

#java -Dcom.sun.jndi.ldap.connect.pool.debug=fine UsePool

这将产生如下所示的输出。

Create com.sun.jndi.ldap.LdapClient@5d173[localhost:389]
Use com.sun.jndi.ldap.LdapClient@5d173
{ou=ou: NewHires, objectclass=objectClass: top, organizationalUnit}
Release com.sun.jndi.ldap.LdapClient@5d173
Use com.sun.jndi.ldap.LdapClient@5d173
{ou=ou: People, objectclass=objectClass: top, organizationalunit}
Release com.sun.jndi.ldap.LdapClient@5d173

您可以通过包含或省略"com\.sun\.jndi\.ldap\.connect\.pool"属性来决定何时以及在何处使用池,从而基于每个上下文控制池。在上一个示例中,如果在创建第二个初始上下文之前从环境属性中删除了此属性,则第二个初始上下文将不使用池化连接。

LDAP 提供程序通过应用程序的指示来跟踪是否正在使用连接。假定维护开放上下文句柄的应用程序正在使用该连接。因此,为了使 LDAP 提供程序正确 管理 池化连接,您必须努力在不再需要的上下文上调用Context\.close\(\)

LDAP 提供程序会自动检测到错误的连接并将其从池中删除。无论是否使用连接池,上下文final以错误的连接结尾的可能性都是相同的。

Creation Timeout

LDAP 服务提供商维护的连接池的大小可能会受到限制; 连接池配置部分对此进行了详细说明。当启用了连接池并且没有池连接可用时,Client 端应用程序将阻塞,await 可用的连接。您可以使用"com\.sun\.jndi\.ldap\.connect\.timeout"环境属性来指定 await 池化连接的时间。如果省略此属性,则应用程序将无限期 await。

此相同的属性还用于指定构建 LDAP 连接的超时时间,如Connection Creation部分中所述。

何时不使用池化!

池化连接将被重用。因此,如果计划在Context实例上执行可能会更改基础连接状态的操作,则不应对该Context实例使用连接池。例如,如果计划在Context实例上调用 Start TLS 扩展操作,或者计划在创建初始上下文之后更改与安全相关的属性(例如"java\.naming\.security\.principal""java\.naming\.security\.protocol"),则不应对该Context使用连接池实例,因为 LDAP 提供程序不跟踪任何此类状态更改。如果在这种情况下使用连接池,则可能会损害应用程序的安全性。