使用自定义套接字工厂汇集LDAP连接

时间:2014-05-27 21:08:11

标签: java sockets ldap jndi connection-pooling

我的Java Web应用程序正在使用LDAP后端进行身份验证/授权。我目前正在使用自定义套接字工厂,并且出于性能原因想要启用连接池。

混乱开始了。

根据标准JNDI教程here如果一个Context实例的“java.naming.ldap.factory.socket”属性设置为自定义套接字工厂类,则它不能使用池连接< / em>的

但是,根据官方(Java 6)JNDI文档here在设置java.naming.ldap.factory.socket环境属性时,允许从自定义套接字工厂连接池。要集成自定义套接字工厂,套接字工厂类必须实现Comparator接口。

激励。到目前为止我做了什么:

  • 我的自定义socketfactory使用host + port
  • 的简单比较实现Comparator<SocketFactory>
  • 在创建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>

帮助!我错过了一些小细节吗?有没有人成功地让这个工作?

1 个答案:

答案 0 :(得分:2)

如果您查看进行比较的actual code,您会发现它确实是一个错误。它期望Comparator<String>而不是Comparator<SocketFactory>。工厂的 classnames 正在通过,而不是工厂本身。在吞并运行时ClassCastException被吞下并false is returned。这就是为什么你看不到你的&#34;调试println()&#34;从compare方法 - 它从未执行过。