【问题标题】:Pooling LDAP connections with custom socket factory使用自定义套接字工厂池化 LDAP 连接
【发布时间】: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


【解决方案1】:

如果您查看进行比较的actual code,您会发现这绝对是一个错误。它期望Comparator&lt;String&gt; 而不是Comparator&lt;SocketFactory&gt;。正在传递工厂的类名,而不是工厂本身。在运行时ClassCastException 被吞并false is returned。这就是为什么您无法从 compare 方法中看到您的“调试 println()”——它从未执行过。

【讨论】:

  • 没想到实际检查 java 源代码。刚刚检查过,当我使用 Comparator&lt;String&gt; 时它可以工作!现在唯一的缺点是,我必须假设同一类的池连接具有相同的特征。所以这将是一个错误,是的。非常感谢您解决这个问题!
  • 附注:我会在哪里将其记录为错误?有什么指点吗?
  • @mvreijn 下次你看到这样的东西时,你可以在这里记录:bugs.java.com 但是这一次(如果你不介意的话)我会节省我们的时间并直接在这里创建一个问题:@ 987654324@
  • 我必须假设同一类的池连接具有相同的特征 你的意思是相同的Class&lt;T&gt; 哪里T extends SocketFactory,对吧?如果这是真的,那么如果您使用T 的实例而不是Class&lt;T&gt; 的实例进行比较会有所不同吗?我的意思是,一般假设(按设计)是给定 ? extends SocketFactory 的任意 2 个实例,我们可以判断我们是否可以互换使用它们创建的连接。
  • @mvreijn 别担心,服务器/端口组合是受管理的。不幸的是,从文档中并不清楚。看看herehereClientIdequals 中处理这些事情。 ClientId 的实例用作 PoolMap 中的键。
猜你喜欢
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
  • 1970-01-01
  • 2018-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多