Menu

Use of Fail-over server set to fail over to secondary server after connection is created.

SKojha
2013-12-06
2014-02-04
  • SKojha

    SKojha - 2013-12-06

    I am trying to use failover server set to switch to secondary if primary is not available. Now, there are following use cases:

    Case 1: (It is working for me)
    During initial connection creation, if primary is not available then connect to secondary server.
    I tried with following sample code and it works:

                String server1Address = "xxx.xxx.xxx.xxx";
        String server2Address = "yyy.yyy.yyy.yyy";
        int server1Port = 10389;
        int server2Port = 10389;
    
        String[] addresses = { server1Address, server2Address };
    
        int[] ports = { server1Port, server2Port };
    
        FailoverServerSet failoverSet = new FailoverServerSet(addresses, ports);
    
        LDAPConnection connection = null;
    
        try
        {
                        // if server1 is not available then it connects to server2
            connection = failoverSet.getConnection();
            System.out.println("Connection: "
                    + connection.getConnectedAddress());
    
                      .... and so on.
    

    Case 2: (Not working for me. Is there any other way provided by unbound id SDK to do it? )
    Once the connection is created, and then primary goes down, it should switch to secondary server. Following code sample illustrates it:

                String server1Address = "xxx.xxx.xxx.xxx";
        String server2Address = "yyy.yyy.yyy.yyy";
        int server1Port = 10389;
        int server2Port = 10389;
    
        String[] addresses = { server1Address, server2Address };
    
        int[] ports = { server1Port, server2Port };
    
        // Create the server set using the address and port arrays.
        FailoverServerSet failoverSet = new FailoverServerSet(addresses, ports);
    
        LDAPConnection connection = null;
    
        try
        {
            connection = failoverSet.getConnection();
    
                        //do some operation with this open connection
                        //do some more operation
                        //In the meantime primary server goes down, will it by default switch to secondary server? 
                        //Is there some option to do it from unbound id sdk?
    
            System.out.println("Connection: "
                    + connection.getConnectedAddress());
    
     
  • Neil Wilson

    Neil Wilson - 2013-12-06

    It sounds like what you want to do could be accomplished by using an LDAPConnectionPool rather than an individual LDAPConnection. Even if you only ever intend to have a single connection established at any time, using an LDAPConnectionPool can help hide problems from your application that are related to a directory server going down or a connection becoming unusable.

    Rather than using something like:

     FailoverServerSet failoverSet = new FailoverServerSet(addresses, ports);
     LDAPConnection connection = failoverSet.getConnection();
     connection.bind(bindDN, password);
     // Do some number of operations like the following:
     SearchResult searchResult = connection.search(baseDN, scope, filter);
    

    You could instead do the following:

     FailoverServerSet failoverSet = new FailoverServerSet(addresses, ports);
     BindRequest bindRequest = new SimpleBindRequest(bindDN, password);
     LDAPConnectionPool pool = new LDAPConnectionPool(failoverSet, bindRequest, 1);
     pool.setRetryFailedOperationsDueToInvalidConnections(true);
     // Do some number of operations against the pool like the following:
     SearchResult searchResult = pool.search(baseDN, scope, filter);
    

    In this case, if you perform an operation against the pool and the directory server goes down, then the pool can automatically try to establish a new connection (using the server set logic, so it might go to a different server if the primary server is unavailable) and retry the operation on that new connection.

    Note that if the primary server goes down and the pool needs to replace a connection to that server with a connection to a secondary server, then that connection to the secondary server will be returned back to the pool and can continue to be used for subsequent requests. If you strongly prefer the primary server over the secondary servers, then you may want to further configure the connection pool and/or the failover server set to specify a maximum connection age so that failback may happen more quickly. You can do that with LDAPConnectionPool.setMaxConnectionAgeMillis (to define a maximum age for all connections in the pool) and/or FailoverServerSet.setMaxFailoverConnectionAgeMillis (to define a maximum age for connections established to any server except the primary). Once a connection has been established for longer than the maximum connection age, it is eligible to be closed and a new one established to take its place. If the primary server is back up by then, then the new connection will be back to that primary server.

     
  • SKojha

    SKojha - 2013-12-11

    Thanks for this nice expalantion. As you explained, we can use "setMaxConnectionAgeMillis/setMaxFailoverConnectionAgeMillis" to fall back to primary.

    Instead of using some predefined time to fall back to primary,

    a. Do we have some mechanism to fall back when it comes up? I was exploring the health checking provided with the SDK. Can we use it for this case?

    b. Does failover server set has some built in mechanism for that purpose?

     
  • Neil Wilson

    Neil Wilson - 2013-12-11

    The only mechanisms that the LDAP SDK has for closing and re-establishing connections that are part of a connection pool are:

    . The length of time that the connection has been established

    . Third-party code indicating that a checked-out connection is no longer valid by releasing it as defunct

    . A determination that the connection is no longer valid by the configured health check mechanism

    There is no link between the server sets and health checks provided by the LDAP SDK, so if a connection is still valid, then a health check will generally not cause it to be closed just because it happens to be established to a less-than-desirable server (because the health check doesn't know whether a server might be less than desirable). But if you wanted to create your own health check, you could potentially build that logic into it.

    Connection pool health checks can invoke custom processing at any or all of the following times:

    . Whenever a connection is first created, the health check can be used to determine whether it is valid

    . Whenever a connection is going to be checked out of the pool, the health check can be used to determine whether it is still valid before making it available to the caller

    . Whenever a connection is going to be released back to the pool, the health check can be used to determine whether it is still valid before putting it back in the pool

    . If an exception is encountered by an operation processed against the pool directly (this can't be done for operations processed on connections the caller has checked out of the pool)

    . Whenever the background health check thread runs, you can invoke custom processing for any connection that is not in use for processing operations

    If you have a well-defined set of preferred and non-preferred servers, you could write a custom health check that can potentially perform the failback more quickly. For example, when performing health checking by the background health check thread, you could first see if a connection is established to a non-preferred server and if so then see if a preferred server is available. If a preferred server is available, then you could have the health check indicate that the connection to the non-preferred server is no longer valid so that it will be closed and the server set will be used to create a new connection (presumably to the preferred server).

    But ultimately, this is probably overkill. With the failover server set's ability to set an alternate maximum age for connections to non-preferred servers, you can have this be a relatively low timeout so that failback will happen pretty quickly. If the preferred server is still down when the failover connections have expired, then the server set will create new connections that will have to go to a non-preferred server, but they'll still have the benefit of the shorter timeout.

     
  • SKojha

    SKojha - 2014-02-04

    While using the failover server set,
    a. is there a way to specify the LDAP error codes to failover?
    b. Currently, on which error codes the failover is based on?
    c. As I understand, there is retry mechanism. Can you explain that? is it possible to retry a server for specific number of times and then failover to other server in the set?

     
  • Neil Wilson

    Neil Wilson - 2014-02-04

    As with all server set implementations, the failover server set only controls the servers to which connections will be established. All connections in the pool are considered equally well-suited for processing any request, so failover and load balancing are really based on the set of servers to which connections are established. The connection pool does not do operation-based load balancing or failover, and it will not ever be updated to do so because that is dramatically more complex, and it is much better to accomplish that with multiple connection pools (one pool per server) rather than a single connection pool that tries to do everything.

    But to answer your questions:

    a. If you process an operation in the context of the pool (e.g., using the LDAPConnnectionPool.search method instead of checking out a connection, using the LDAPConnection.search method, and then releasing that connection), then the connection pool will invoke the configured health check's ensureConnectionValidAfterException method after any operation that does not complete successfully. If the ensureConnectionValidAfterException method throws an exception, then the connection is no longer considered valid and it will be closed and the configured server set will be used to establish a new one to take its place. You can write your own custom health check to do whatever you want in this case.

    b. The default ensureConnectionValidAfterException method uses the ResultCode.isConnectionUsable method in an attempt to determine whether the connection is still valid. The result codes for which a connection will be considered no longer usable include:
    - Operations Error (1)
    - Protocol Error (2)
    - Busy (51)
    - Unavailable (52)
    - Unwilling to Perform (53)
    - Other (80)
    - Server Down (81)
    - Local Error (82)
    - Encoding Error (83)
    - Decoding Error (84)
    - Timeout (85)
    - No Memory (90)
    - Connect Error (91)

    c. The connection pool retry mechanism (which can be enabled using the setRetryFailedOperationsDueToInvalidConnections method) makes it possible to automatically retry any operation that fails in a way that indicates that the connection is no longer valid. Again, this is only available for operations that you process against the pool itself and not for operations you process on connections that you have checked out of the pool. If an attempted operation does not complete successfully, then the health check's ensureConnectionValidAfterException method will be used to determine if the connection is still valid. If the connection is not valid and the operation is one that should be retried, then the connection pool will use the server set to create a new connection (which may be to the same or a different server) and will retry the operation over that connection. There is only a single retry for any operation, and this is not configurable.

     

Log in to post a comment.