Menu

How does autoreconnect work?

Abid
2011-10-19
2013-06-13
  • Abid

    Abid - 2011-10-19

    Hi again,

    we tried the reconnect option in LDAPConnectionOptions (performing simple bind authentication) for an autoreconnect, but it doesn't seem to work.

    We used the following code:

    LDAPConnectionOptions options = new LDAPConnectionOptions();
    options.setAutoReconnect(true);
    options.setConnectTimeoutMillis(60000);
    LDAPConnection con = new LDAPConnection(options);
    con.connect(host, port);
    con.bind(rootDn, passwd);
    We did the following:
    1. run the code above
    2. perform a simple search against a running server
    3. stop the server
    4. again perform a second simple search
    The second search fails straight away:
    [quote]LDAPSearchException(resultCode=81 (server down), numEntries=0, numReferences=0, errorMessage='The connection is not esta
    blished.')
        at com.unboundid.ldap.sdk.LDAPConnection.search(LDAPConnection.java:3054)
        at com.unboundid.ldap.sdk.LDAPConnection.search(LDAPConnection.java:2619)
        at com.abid.ldap.unboundid.App.performSimpleSearch(App.java:100)
        at com.abid.ldap.unboundid.TestHA.testReconnect(TestHA.java:80)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:592)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
        at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
        at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
    Caused by: LDAPException(resultCode=81 (server down), errorMessage='The connection is not established.')
        at com.unboundid.ldap.sdk.LDAPConnection.registerResponseAcceptor(LDAPConnection.java:3697)
        at com.unboundid.ldap.sdk.SearchRequest.processAsync(SearchRequest.java:1341)
        at com.unboundid.ldap.sdk.SearchRequest.process(SearchRequest.java:1104)
        at com.unboundid.ldap.sdk.LDAPConnection.search(LDAPConnection.java:3044)
        ... 27 more
    [/quote]
    The connectTimeoutMillis seems not to be considered at all as the second search fails straight away.
    Did we forget anything? And how often is the reconnect to be tried? Once?
    Regards,
    Abid
    
     
  • Abid

    Abid - 2011-10-19

    Something went wrong with the formatting…

    Hi again,

    we tried the reconnect option in LDAPConnectionOptions (performing simple bind authentication) for an autoreconnect, but it doesn't seem to work.

    We used the following code:

    LDAPConnectionOptions options = new LDAPConnectionOptions();
    options.setAutoReconnect(true);
    options.setConnectTimeoutMillis(60000);
    LDAPConnection con = new LDAPConnection(options);
    con.connect(host, port);
    con.bind(rootDn, passwd);
    

    We did the following:
    1. run the code above
    2. perform a simple search against a running server
    3. stop the server
    4. again perform a second simple search

    The second search fails straight away:

    LDAPSearchException(resultCode=81 (server down), numEntries=0, numReferences=0, errorMessage='The connection is not esta
    blished.')
    at com.unboundid.ldap.sdk.LDAPConnection.search(LDAPConnection.java:3054)
    at com.unboundid.ldap.sdk.LDAPConnection.search(LDAPConnection.java:2619)
    at com.abid.ldap.unboundid.App.performSimpleSearch(App.java:100)
    at com.abid.ldap.unboundid.TestHA.testReconnect(TestHA.java:80)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:592)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
    Caused by: LDAPException(resultCode=81 (server down), errorMessage='The connection is not established.')
    at com.unboundid.ldap.sdk.LDAPConnection.registerResponseAcceptor(LDAPConnection.java:3697)
    at com.unboundid.ldap.sdk.SearchRequest.processAsync(SearchRequest.java:1341)
    at com.unboundid.ldap.sdk.SearchRequest.process(SearchRequest.java:1104)
    at com.unboundid.ldap.sdk.LDAPConnection.search(LDAPConnection.java:3044)
    … 27 more

    The connectTimeoutMillis seems not to be considered at all as the second search fails straight away.

    Did we forget anything? And how often is the reconnect to be tried? Once?

    Regards,

    Abid

     
  • Abid

    Abid - 2011-10-19

    OK, I read that connectTimoutMillis is only considered when running in sychronous mode. But even this fails:

    LDAPSearchException(resultCode=91 (connect error), numEntries=0, numReferences=0, errorMessage='An error occurred while
    attempting to connect to server localhost:10389:  java.io.IOException: An error occurred while attempting to establish a
    connection to server localhost:10389:  java.net.ConnectException: Connection refused: connect')
    at com.unboundid.ldap.sdk.LDAPConnection.search(LDAPConnection.java:3054)
    at com.unboundid.ldap.sdk.LDAPConnection.search(LDAPConnection.java:2619)
    at com.abid.ldap.unboundid.App.performSimpleSearch(App.java:100)
    at com.abid.ldap.unboundid.TestHA.testReconnect(TestHA.java:81)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:592)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
    Caused by: LDAPException(resultCode=91 (connect error), errorMessage='An error occurred while attempting to connect to s
    erver localhost:10389:  java.io.IOException: An error occurred while attempting to establish a connection to server loca
    lhost:10389:  java.net.ConnectException: Connection refused: connect')
    at com.unboundid.ldap.sdk.LDAPConnection.connect(LDAPConnection.java:705)
    at com.unboundid.ldap.sdk.LDAPConnection.connect(LDAPConnection.java:639)
    at com.unboundid.ldap.sdk.LDAPConnection.reconnect(LDAPConnection.java:762)
    at com.unboundid.ldap.sdk.LDAPConnectionInternals.sendMessage(LDAPConnectionInternals.java:461)
    at com.unboundid.ldap.sdk.LDAPConnection.sendMessage(LDAPConnection.java:3555)
    at com.unboundid.ldap.sdk.SearchRequest.processSync(SearchRequest.java:1414)
    at com.unboundid.ldap.sdk.SearchRequest.process(SearchRequest.java:1100)
    at com.unboundid.ldap.sdk.LDAPConnection.search(LDAPConnection.java:3044)
    … 27 more
    Caused by: java.io.IOException: An error occurred while attempting to establish a connection to server localhost:10389:
    java.net.ConnectException: Connection refused: connect
    at com.unboundid.ldap.sdk.LDAPConnectionInternals.<init>(LDAPConnectionInternals.java:142)
    at com.unboundid.ldap.sdk.LDAPConnection.connect(LDAPConnection.java:696)
    … 34 more

    The failure appears straight away, after performing a second search operation (see post above), no timeout considered and autoreconnect also doesn't seem to work…?

     
  • Neil Wilson

    Neil Wilson - 2011-10-19

    The auto-reconnect option provides the ability for a connection that is no longer valid to attempt to automatically re-establish itself and re-authenticate, assuming that the server itself is still up.  It is primarily useful in the case of a connection being closed because it was idle for too long or becoming invalid as a result of a short-lived network problem, although it may also work in some kinds of load-balanced environments.  If the server is still down and the re-connect attempt is unsuccessful, then the connection will be considered invalid and no further automatic reconnect attempts will be made.

    The connect timeout specifies the maximum length of time that the LDAP SDK will wait for a response from a connection attempt.  In your case, it gets a response immediately from the target system saying that there's nothing listening on the specified address and port, so it doesn't need to wait for the full timeout period.  The connect timeout is useful to ensure that the client doesn't block for too long if the machine itself is offline or unreachable (in which case you will never get a response), but it doesn't cause the SDK to keep trying for the full length of time if the connection attempt is rejected.  Also, whether or not you're using synchronous mode has no impact on how the connect timeout is handled.

    The best solution for what you're trying to do would actually be to use a connection pool, even if that pool only has a single connection.  Connection pools have excellent support for connection management and dealing with connections that have become invalid, and they also offer much better options for failover in that they can be configured with information about multiple servers (through the ServerSet API) so that the best server can be selected.  In most cases, you can simply use a connection pool like a regular connection, so you can call methods like add, compare, delete, etc., and the pool will automatically check out a connection, perform the requested operation, and release the connection back to the pool, and will automatically handle failures which may indicate that the connection is no longer valid.  As of the most recent version, you can even configure the connection pool to re-try an operation on a new connection (potentially even to a different server) if the first attempt failed in a way that indicates the connection used for that attempt may no longer be valid.

    Neil

     
  • Abid

    Abid - 2011-10-20

    Thanks a lot for your detailed answer.

    But for what do I  need the re-try option in this scenerio as I already have configured a failover server set which switches automaticall to another server if any operation fails?

     
  • Neil Wilson

    Neil Wilson - 2011-10-20

    Server sets are used only at the time that connections are established.  If an operation fails in a manner that indicates the connection may no longer be available, then a connection pool will always close that connection and try to re-establish a new one to take its place (which may or may not be to the same server depending on the server availability and the configured server set).  However, unless the auto-retry capability is enabled, then the failed operation will cause an exception to be thrown so that operation will be reported as a failure to the client.  If the auto-retry feature is enabled, then the failure will be intercepted and the operation may be automatically re-tried so that the client never sees the original failure.

    Neil

     
  • Abid

    Abid - 2011-10-21

    Thanks, got it. But I wonder about retrying a write operation. It could be that the a write operation succeeded but the response didn't reach the client (for any kind of reasons). If he now performs a retry the same write operation will be performed twice.

     
  • Neil Wilson

    Neil Wilson - 2011-10-21

    It is possible that a failure was perceived by the client but that the server still went ahead and processed the requested operation (e.g., if the client doesn't receive a response in a timely manner, as controlled by the response timeout for that operation, or if the connection was lost before the response could be received, perhaps because the server crashed after completing the write but before sending the response).  If it is a write operation, and if the newly-created connection goes to a different server, then it is possible that it could result in a replication conflict.  However, any decent directory server should be able to resolve that easily, especially since it's going to be exactly the same operation.

    Nevertheless, I can update the connection pool implementation to make it possible to control the setting based on the type of operation.  It should be possible to do that in a backward-compatible manner.

    Neil

     
  • Neil Wilson

    Neil Wilson - 2011-11-28

    I have updated the connection pool implementations so that it is now possible to control retry on a per-operation-type basis.

    Neil

     

Log in to post a comment.