Как переподключиться при перезапуске сервера LDAP?

У меня есть ситуация, когда через программу Java я создаю javax.naming.ldap.LdapContext и выполняю над ней операцию search(), которая создает базовое соединение. Затем я усыпляю поток Java-приложения, во время которого перезапускаю сервер LDAP (на заметку — OpenLDAP). Когда поток приложения просыпается и пытается выполнить какую-либо операцию над созданным ранее LdapContext, он выдает "CommunicationException: Connection is closed".

Я хочу иметь возможность восстановить соединение.

Я вижу, что у LdapContext есть метод reconnect(), где я передаю элементы управления как null. Однако это не имеет никакого эффекта. Что я увидел в реализации Sun LDAP, так это то, что во время перезапуска сервера LDAP ConnectionPool, поддерживаемый реализацией Sun, помечал базовый экземпляр com.sun.jndi.ldap.LdapClient с помощью "usable=false". При вызове reconnect() он просто вызывает ensureOpen(), который снова проверяет, является ли флаг usable false или нет - если он false; затем он выдает CommunicationException - так что вернемся к исходной точке.

Мой вопрос: как приложение Java выдерживает перезапуск внешнего сервера LDAP? Неужели создание новых LdapContext снова единственный выход? Цените любые идеи.

Вот трассировка стека исключения:

javax.naming.CommunicationException: connection closed [Root exception is java.io.IOException: connection closed]; remaining name 'uid=foo,ou=People,dc=example,dc=com'
at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1979)
at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1824)
at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1749)
at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:368)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:338)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:321)
at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:248)
Caused by: java.io.IOException: connection closed
at com.sun.jndi.ldap.LdapClient.ensureOpen(LdapClient.java:1558)
at com.sun.jndi.ldap.LdapClient.search(LdapClient.java:504)
at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1962)
... 26 more

person Anand    schedule 09.01.2012    source источник
comment
Я не думаю, что проблема должна возникнуть после перезапуска сервера, если вы не изменили ни одного пользователя Bind.   -  person Muhammad Imran Tariq    schedule 09.01.2012
comment
Привет, Имран, к сожалению, все операции с LdapContext завершаются с ошибкой CommunicationException после перезапуска сервера LDAP.   -  person Anand    schedule 09.01.2012
comment
Не могли бы вы поделиться кодом, как вы создаете соединение и используете его для поиска?   -  person Muhammad Imran Tariq    schedule 10.01.2012
comment
Я использую ActiveDirectory. Я перезапустил сервер и поиск. Это не дало мне никаких исключений, и поиск завершился.   -  person Muhammad Imran Tariq    schedule 10.01.2012
comment
Код примерно такой: Ограничения SearchControls = new SearchControls(); ограничения.setSearchScope(SearchControls.SUBTREE_SCOPE); Строка searchName = тест; Строка baseDN = dc=foo,dc=com; NamingEnumeration namingEnum = ldapContext.search(baseDN, searchName, ограничения); --- скажем, я помещаю это в цикл с некоторой задержкой... и затем перезапускаю сервер LDAP, когда цикл находится в спящем режиме. При следующем пробуждении; операция search() завершается с ошибкой, выбрасывая CommunicationException   -  person Anand    schedule 11.01.2012
comment
Это исключение может возникнуть при перезапуске сервера ldap. Можете ли вы подтвердить, что при продолжении цикла сервер ldap снова работал после перезапуска.   -  person Muhammad Imran Tariq    schedule 12.01.2012
comment
Да, как я уже сказал, когда шлейф спит - я перезапускаю сервер. Итак, когда цикл просыпается - сервер снова возвращается - однако LdapContext.search() терпит неудачу.   -  person Anand    schedule 13.01.2012
comment
@Ананд: у меня такая же проблема, как у тебя. Поскольку 13 января активности нет, кажется, вы уже нашли решение. Буду признателен, если вы поделитесь им с нами. Спасибо   -  person Oueslati Bechir    schedule 13.12.2012
comment
@LBechir: Нет, с Sun/Oracle LDAP Impl решения нет :-/. Тем не менее, нужно сохранить это как известную проблему.   -  person Anand    schedule 15.12.2012


Ответы (4)


Просто включите пул соединений JNDI, и обо всем позаботятся за вас за кулисами. См. Руководство JNDI по функциям и документацию поставщика LDAP. Он контролируется всего парой свойств.

person user207421    schedule 04.08.2013

UnboundID LDAP SDK предоставляет средства для автоматического подключения, при этом эта операция автоматического повторного подключения невидима для клиент.

person Terry Gardner    schedule 09.01.2012

У нас была такая проблема на работе. Решение, которое мы придумали (возможно, не лучший ответ). Нужно было создать сторожевой поток, который проверял бы соединение с некоторой фиксированной скоростью. Если соединение не работало, оно повторно инициализировало соединение с LDAP.

person lordoku    schedule 03.08.2013

Следует отметить, что это в основном связано с пулом соединений LDAP. Как определено здесь:

Соединение извлекается из пула, используется, возвращается в пул, а затем снова извлекается из пула для другого экземпляра Context.

Таким образом, повторное использование предыдущего соединения может вызвать такую ​​проблему:

Вы можете протестировать поведение без использования пула соединений LDAP, установив

com.sun.jndi.ldap.connect.pool=false

Также другой возможной причиной может быть тайм-аут чтения операций LDAP. Фактически операция чтения не уведомляется о закрытии LDAP-сервера по истечении определенного тайм-аута. Для получения дополнительной информации вы можете просмотреть эту ссылку.

person Oueslati Bechir    schedule 11.02.2013
comment
Пул соединений по умолчанию отключен. Я не вижу особого смысла в вашем последнем абзаце. Если сервер выйдет из строя во время чтения, вы обязательно получите уведомление. - person user207421; 26.08.2016