【发布时间】:2014-05-27 21:08:11
【问题描述】:
我的 Java Web 应用程序正在使用 LDAP 后端进行身份验证/授权。我目前正在使用自定义套接字工厂,并且出于性能原因想要启用连接池。
混乱开始了。
根据标准 JNDI 教程 here,如果 Context 实例的“java.naming.ldap.factory.socket”属性设置为自定义套接字工厂类,则不能使用池连接.
但是,根据官方 (Java 6) JNDI 文档here,当设置了 java.naming.ldap.factory.socket 环境属性时,允许池化来自自定义套接字工厂的连接。对于要池化的自定义套接字工厂,套接字工厂类必须实现 Comparator 接口。
鼓励。到目前为止我做了什么:
- 我的自定义socketfactory实现
Comparator<SocketFactory>简单对比host+port - 在创建
LdapContext时,我会使用env.put("java.naming.ldap.factory.socket", "portal.ldap.util.PortalSocketFactory")和env.put("com.sun.jndi.ldap.connect.pool", "true") - 我的 Tomcat 服务器以
-Dcom.sun.jndi.ldap.connect.pool.initsize=10 -Dcom.sun.jndi.ldap.connect.pool.maxsize=20 -Dcom.sun.jndi.ldap.connect.pool.prefsize=10 -Dcom.sun.jndi.ldap.connect.pool.timeout=300000 -Dcom.sun.jndi.ldap.connect.pool.protocol="plain ssl" -Dcom.sun.jndi.ldap.connect.pool.debug="all"启动
接下来,进行测试。我连接到应用程序,它连接到 LDAP 服务器,然后看到 - 创建了一个连接池。显然,我的自定义 socketfactory 被接受了:
com.sun.jndi.ldap.pool.Pool@26cd2192 {}.get(): 172.17.2.91:636:ssl::portal.ldap.util.PortalSocketFactory:cn=PortalProxy,ou=sa,o=config
com.sun.jndi.ldap.pool.Pool@26cd2192 {}.size: 0
com.sun.jndi.ldap.pool.Pool@26cd2192 {}.get(): creating new connections list for 172.17.2.91:636:ssl::portal.ldap.util.PortalSocketFactory:cn=PortalProxy,ou=sa,o=config
com.sun.jndi.ldap.pool.Connections@65fe28a7.init size=10; size: 0
com.sun.jndi.ldap.pool.Connections@65fe28a7.max size=20; size: 0
com.sun.jndi.ldap.pool.Connections@65fe28a7.preferred size=10; size: 0
Create com.sun.jndi.ldap.LdapClient@127e942f[172.17.2.91:636]
<snip>
Create com.sun.jndi.ldap.LdapClient@3c7038b9[172.17.2.91:636]
com.sun.jndi.ldap.pool.Pool@26cd2192 {172.17.2.91:636:ssl::portal.ldap.util.PortalSocketFactory:cn=PortalProxy,ou=sa,o=config=com.sun.jndi.ldap.pool.ConnectionsRef@6b9c18ae}.get(): size after: 1
com.sun.jndi.ldap.pool.Connections@65fe28a7.get(): before; size: 10
ConnectionDesc.tryUse() com.sun.jndi.ldap.LdapClient@127e942f idle
com.sun.jndi.ldap.pool.Connections@65fe28a7.get(): use com.sun.jndi.ldap.LdapClient@127e942f; size: 10
Use com.sun.jndi.ldap.LdapClient@127e942f
com.sun.jndi.ldap.pool.Connections@65fe28a7.get(): after; size: 10
但是你猜对了,有些东西已经烂了。现在,每次应用程序连接时,都会实例化一个新池!我可以看到这些连接实际上是池化的,因为在配置的 300 秒后,它们会过期并从池中删除:
ConnectionDesc.expire(): not expired com.sun.jndi.ldap.LdapClient@e6c7a64 idle
ConnectionDesc.expire(): expired com.sun.jndi.ldap.LdapClient@39579371 idle
com.sun.jndi.ldap.pool.Connections@13a9192b.expire(): removing com.sun.jndi.ldap.LdapClient@39579371 expired; size: 10
Expired com.sun.jndi.ldap.LdapClient@39579371 expired
ConnectionDesc.expire(): expired com.sun.jndi.ldap.LdapClient@2ada52a1 idle
com.sun.jndi.ldap.pool.Connections@13a9192b.expire(): removing com.sun.jndi.ldap.LdapClient@2ada52a1 expired; size: 9
Expired com.sun.jndi.ldap.LdapClient@2ada52a1 expired
<and so on>
帮助!我是否遗漏了一些小细节?有没有人成功地让这个工作?
【问题讨论】:
-
凭直觉,我在我的 socketfactory 的
compare()方法中添加了一个调试 println(),并且... 它从未被LdapPoolManager调用 !! -
奇怪的是他们指定了 Comparator 而不是 Comparable。对于套接字工厂对象来说, compareTo() 本身比比较两个不同的对象更有意义,其中一个对象可能总是它自己。
-
同意。据我了解(从我再也找不到的帖子中)创建了一个新的 socketfactory(自定义类)来执行比较。似乎有点可疑。
-
我强烈建议您迁移到当前的 LDAP API。许多人已经提供了所有的池类。 -吉姆
标签: java sockets ldap jndi connection-pooling