我们正在从 Java (Spring Boot) 应用程序连接到 LDAP (OpenLDAP) 服务。我们遇到了 TLS 和内存使用问题。
背景
- 我们正在使用 Apache Directory LDAP API (v2) 库进行连接。
- 我们正在使用与 LDAP 服务器的池连接。
- 我们使用 StartTLS 来保护 Java 服务和 LDAP 服务器之间的连接。
- 我们实际上并没有从这里对 LDAP 服务器进行身份验证!
- 我们的 API 网关处理身份验证(针对相同的 LDAP 服务)。
- 我们在代码中做了两件事:
- 获取更多关于用户的数据(当接收 API 请求时)和
- 从使其与另一个源保持同步的服务更新 LDPA。
内存问题
我们在 Java 服务上遇到内存不足错误。堆栈跟踪如下所示:
Exception in thread "pool-2454-thread-1" java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.resize(HashMap.java:704)
at java.util.HashMap.putVal(HashMap.java:629)
at java.util.HashMap.put(HashMap.java:612)
at sun.security.util.MemoryCache.put(Cache.java:365)
at sun.security.ssl.SSLSessionContextImpl.put(SSLSessionContextImpl.java:181)
at sun.security.ssl.ClientHandshaker.serverFinished(ClientHandshaker.java:1293)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:379)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1082)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:1010)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1032)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:913)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:783)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:626)
at org.apache.mina.filter.ssl.SslHandler.unwrap(SslHandler.java:774)
at org.apache.mina.filter.ssl.SslHandler.unwrapHandshake(SslHandler.java:710)
at org.apache.mina.filter.ssl.SslHandler.handshake(SslHandler.java:596)
at org.apache.mina.filter.ssl.SslHandler.messageReceived(SslHandler.java:355)
at org.apache.mina.filter.ssl.SslFilter.messageReceived(SslFilter.java:517)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:650)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:49)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1128)
at org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived(IoFilterAdapter.java:122)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:650)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireMessageReceived(DefaultIoFilterChain.java:643)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(AbstractPollingIoProcessor.java:539)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$1200(AbstractPollingIoProcessor.java:68)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.process(AbstractPollingIoProcessor.java:1222)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.process(AbstractPollingIoProcessor.java:1211)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:683)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
2020-10-13 10:03:23.388677637+03:00 Starting: /etc/alternatives/jre/bin/java -Xms128M -Xmx256M -Dlogging.config=/services/registry.svc/log4j2.json -jar
我的同事在 JVM 上调试了一个具有 128m 内存的简单 API,LDAP 池看起来使用了大量内存而没有做太多事情:
我注意到代码在进行unbind
查询后正在执行。这闻起来不对 - 我们没有绑定每个用户,我们有一个(只读)用户与 API 服务连接,这允许他们读取有关用户连接的详细信息以及同步服务的另一个(读写)用户. 据我了解,绑定就像登录和使用其他连接池,这是您每次都不做的事情。我想知道通过解除绑定但不关闭我们是否会留下僵尸连接并吃掉记忆?
SSL 问题
但是,如果我们不取消绑定,我们会在日志中大量出现以下错误,但没有任何合理的方法可以找到它的来源。没有找到太多关于它的东西:
2020-10-14 11:08:57.817 [NioProcessor-3] WARN org.apache.directory.ldap.client.api.LdapNetworkConnection - Outbound done [MDC: {}]
javax.net.ssl.SSLException: Outbound done
at org.apache.mina.filter.ssl.SslFilter.messageReceived(SslFilter.java:513) ~[mina-core-2.1.3.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:650) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:49) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:1128) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived(IoFilterAdapter.java:122) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:650) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireMessageReceived(DefaultIoFilterChain.java:643) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(AbstractPollingIoProcessor.java:539) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$1200(AbstractPollingIoProcessor.java:68) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.process(AbstractPollingIoProcessor.java:1222) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.process(AbstractPollingIoProcessor.java:1211) [mina-core-2.1.3.jar:?]
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:683) [mina-core-2.1.3.jar:?]
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64) [mina-core-2.1.3.jar:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_261]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_261]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_261]
可能的解决方法
我确实在网上找到了一些示例,这些示例建议了以下模式:
if (connection.isConnected() && connection.isAuthenticated()) {
connection.bind();
try {
// do stuff
} finally {
connection.unBind();
}
但这感觉不对 - 或者至少是一种解决方法
问题
所以,我的问题分为两部分:
- 我们是否应该绑定和取消绑定每个查询(即使我们始终以同一个用户身份进行身份验证),或者我们是否会失去池的好处?
javax.net.ssl.SSLException: Outbound done
有没有人有关于异常的任何信息?它是否相关以及如何解决?