Uploaded image for project: 'Ruby Driver'
  1. Ruby Driver
  2. RUBY-2144

Redundant socket connections during address resolution

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: 2.11.3
    • Fix Version/s: 2.12.0.rc0, 2.11.4
    • Component/s: Connections
    • Labels:
      None
    • Backwards Compatibility:
      Fully Compatible
    • Case:

      Description

      When the driver has to connect to a DNS-resolved host name, it currently performs the following operations:

      1. Get IP addresses that the host name resolves to (ipv4 only for localhost, any for other host names)
      2. Create a socket and connect to each resolved address in turn.
      3. Return the first address connection to which succeeded.
      4. Create another socket to the address in step 3, connect this socket and use it for subsequent operations.

      The driver should instead use the socket obtained in step 2 for operations.

      ----------------

      With a small patch to the driver we can observe multiple connections being established during Mongo::Server::ConnectionPool#create_and_add_connection:

      diff --git a/lib/mongo/socket/tcp.rb b/lib/mongo/socket/tcp.rb
      index ca4123ff..defbc659 100644
      --- a/lib/mongo/socket/tcp.rb
      +++ b/lib/mongo/socket/tcp.rb
      @@ -40,6 +40,7 @@ module Mongo
             def connect!
               Timeout.timeout(options[:connect_timeout], Error::SocketTimeoutError) do
                 socket.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1)
      +          puts "#{DateTime.now.strftime("%T:%L")} - connect! #{host}:#{port} - #{socket.inspect} - #{Thread.current.backtrace.join("\n")}"
                 handle_errors { socket.connect(::Socket.pack_sockaddr_in(port, host)) }
                 self
               end
      

      The following test code (loading the patched driver) shows the socket descriptors being created once, but connected twice:

      require 'bundler/inline'
       
      gemfile do
        source 'https://rubygems.org'
       
        gem 'mongo', path: "/path/to/mongo-ruby-driver"
      end
       
      Mongo::Logger.logger.level = Logger::FATAL
       
      client = Mongo::Client.new([ '127.0.0.1:27017' ], database: 'mydb', replica_set: 'replset', min_pool_size: 1, max_pool_size: 3)
      sleep 1
      client.close
      

      Cluster is a PSS.

      Sample Output

      Test code appends backtrace (removed below).

      min_pool: 0
      14:40:31:566 - connect! 127.0.0.1:27017 - #<Socket:fd 10>
      14:40:31:566 - connect! 127.0.0.1:27017 - #<Socket:fd 10>
      14:40:31:571 - connect! 127.0.0.1:27018 - #<Socket:fd 11>
      14:40:31:572 - connect! 127.0.0.1:27017 - #<Socket:fd 12>
      14:40:31:573 - connect! 127.0.0.1:27017 - #<Socket:fd 12>
      14:40:31:574 - connect! 127.0.0.1:27019 - #<Socket:fd 13>
      14:40:31:576 - connect! 127.0.0.1:27018 - #<Socket:fd 11>
      14:40:31:576 - connect! 127.0.0.1:27019 - #<Socket:fd 13>
       
      min/max_pool: 1
      13:53:04:736 - connect! 127.0.0.1:27017 - #<Socket:fd 10>
      13:53:04:736 - connect! 127.0.0.1:27017 - #<Socket:fd 10>
      13:53:04:746 - connect! 127.0.0.1:27018 - #<Socket:fd 11>
      13:53:04:747 - connect! 127.0.0.1:27017 - #<Socket:fd 12>
      13:53:04:751 - connect! 127.0.0.1:27018 - #<Socket:fd 11>
      13:53:04:747 - connect! 127.0.0.1:27017 - #<Socket:fd 12>
      13:53:04:753 - connect! 127.0.0.1:27019 - #<Socket:fd 13>
      13:53:04:753 - connect! 127.0.0.1:27019 - #<Socket:fd 13>
      13:53:04:760 - connect! 127.0.0.1:27018 - #<Socket:fd 14>
      13:53:04:761 - connect! 127.0.0.1:27018 - #<Socket:fd 14>
      13:53:04:767 - connect! 127.0.0.1:27019 - #<Socket:fd 15>
      13:53:04:776 - connect! 127.0.0.1:27019 - #<Socket:fd 15>
      13:53:04:778 - connect! 127.0.0.1:27017 - #<Socket:fd 16>
      13:53:04:780 - connect! 127.0.0.1:27017 - #<Socket:fd 16>
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              oleg.pudeyev Oleg Pudeyev
              Reporter:
              alex.bevilacqua Alex Bevilacqua
              Participants:
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: