首頁>Program>source

我们正在从Java(春季啟動)應用程式連線到LDAP(OpenLDAP)服務. TLS和記憶體使用存在問题。

Background

  • We are using the Apache Directory LDAP API (v2) library for the connection.
  • We are using a pooled connection to the LDAP server.
  • We are using StartTLS to secure the connections between the Java service and the LDAP server.
  • We are not actually authenticating against the LDAP server from here!
    • Our API gateway handles authentication (against the same LDAP service).
    • We are doing two thing in our code:
      • Fetching more data on the user (when receiving API requests) and
      • Updating the LDPA from a service that keeps it synchronised with another source.

Memory Issues

我们在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 Issues

但是,如果我们不取消繫結,則会在日志中大量出現以下錯誤,而没有任何合理的方法来查詢錯誤的来源.没發現太多东西

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]

Possible Work-Around

我確實在網上找到了一些示例,這些示例提出了如下模式:

if (connection.isConnected() && connection.isAuthenticated()) {
    connection.bind();
try {
    // do stuff
} finally {
    connection.unBind();
}

但這感覺不對-至少是一種解決方法

Question

所以,我的問题分為两个部分:

  1. 我们應该繫結和取消繫結每个查詢(即使我们始终以相同的使用者身份进行身份驗證),還是失去了池的好處?
  2. 有人在 javax.net.ssl.SSLException: Outbound done上有任何資訊吗 例外? 它相關並且如何解決?
最新回復
  • 7月前
    1 #

    所以,似乎我關闭連線錯誤.我假設,如果从池中获得連線,如果"關闭"連線,它將返迴到池中.似乎它關闭了它,但將其保留在池中(可能是借来的,也许只是無法使用,没有进行那麼远的研究).看来我需要將其返迴到池中,並為此保留對池的引用。

    我有一个函式(實際上是註入服務)来處理池並返迴連線.我想做的是:

    try (final LdapConnection connection = ldapService.getConnection()) {
       // Do stuff with connection
    }
    

    我最终要做的是定義一个像這樣的類:

    /**
     * Wraps a connection from a connection pool such that close with release it back to the pool.
     *
     * <p>You need a reference to the pool in order to release it, so using a wrapper</p>
     */
    public class PooledLdapConnection implements Closeable {
      private final LdapConnection connection;
      private final LdapConnectionPool pool;
      public PooledLdapConnection(final LdapConnection connection, final LdapConnectionPool pool) {
        this.connection = connection;
        this.pool = pool;
      }
      public LdapConnection getConnection() {
        return connection;
      }
      @Override
      public void close() throws IOException {
        if (pool != null) {
          try {
            pool.releaseConnection(connection);
          } catch (final LdapException e) {
            throw new IOException(e.getMessage(), e);
          }
        }
      }
    }
    

    然後我的LDAP服務現在在函式中返迴该值,而不仅仅是返迴 pool.getConnection() 我返迴 new PooledLdapConnection(pool.getConnection(), pool)

    那我可以

    try (final PooledLdapConnection connection = ldapService.getConnection()) {
       // Do stuff with connection.getConnection()
    }
    

    ,当它完成並"關闭"時,它實際上只是返迴到池中.我本可以用PooledLdapConnection實現LdapConnection介面,然後簡單地代理除 close之外的所有功能的實現 直接連線到我的基础連線物件,但這很容易,並且如果介面已经更新,也不需要重構。

    我確實覺得這是圖书馆應该為我做的! 池返迴的實現應该是与获得單个連線返迴的實現不同的物件,不同之處在於自動關闭的作用.但這似乎可行。

    我還有一个問题.我们在開發環境中對DNS进行了錯誤配置,因此它指出了尝試連線到LDAP的錯誤服務器.在這種情况下,它仍然会占用連線,直到我们達到Java檔案限製.還没有进一步調查

  • javascript:React中圖像的src引數的變數名
  • php:从臨時表中获取資料