Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The driver should support more than one A record pr host name #20

Open
johnny-egeland opened this issue Sep 21, 2021 · 0 comments
Open

Comments

@johnny-egeland
Copy link

In High Availability setups, there are often two servers set up in a fail-over mode. This means that if one fails, the other immediately takes over. In such cases the DNS server is set up to provide two IP addresses for a DB server hostname. It is then up to the client (driver) to attempt to connect to all provided addresses before reporting a failure to connect.

This is currently not supported by jTDS, meaning it is cumbersome to use in such environments (I need to check which server is up, and change a raw IP in the settings manually). The following patch fixes this issue (however it's quite rudamentary). I'd suggest making this behavior optional, but the patch solves the issue locally for me.

diff --git a/src/main/net/sourceforge/jtds/jdbc/SharedSocket.java b/src/main/net/sourceforge/jtds/jdbc/SharedSocket.java
index d7bcd38..02caca7 100644
--- a/src/main/net/sourceforge/jtds/jdbc/SharedSocket.java
+++ b/src/main/net/sourceforge/jtds/jdbc/SharedSocket.java
@@ -25,6 +25,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.RandomAccessFile;
+import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.NetworkInterface;
 import java.net.Socket;
@@ -275,18 +276,34 @@ class SharedSocket {
       final String bindAddress = connection.getBindAddress();
       final int loginTimeout = connection.getLoginTimeout();
 
-      Socket socket = new Socket();
-      InetSocketAddress address = new InetSocketAddress( host, port );
+      // Resolve all IPs for configured hostname
+      InetAddress[] resolvedAddresses = InetAddress.getAllByName(host);
 
       // call Socket.bind(SocketAddress) if bindAddress parameter is set
-      if( bindAddress != null && ! bindAddress.isEmpty() )
+      String lastExceptionMessage = null;
+      for (InetAddress inetAddress : resolvedAddresses)
       {
-         socket.bind( new InetSocketAddress( bindAddress, 0 ) );
+         try
+         {
+            Socket socket = new Socket();
+            if( bindAddress != null && ! bindAddress.isEmpty() )
+            {
+               socket.bind( new InetSocketAddress( bindAddress, 0 ) );
+            }
+
+            // Try to connect to each of the given addresses
+            InetSocketAddress address = new InetSocketAddress(inetAddress, port);
+            socket.connect(address, loginTimeout * 1000);
+            return socket;
+         }
+         catch (IOException ex)
+         {
+             // NO-OP: Continue
+            lastExceptionMessage = ex.getMessage();
+         }
       }
 
-      // establish connection
-      socket.connect( address, loginTimeout * 1000 );
-      return socket;
+      throw new IOException("Unable to connect to SQL server. Last error: " + lastExceptionMessage);
    }
 
    String getMAC()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant