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

Redundant socket connections during address resolution

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 2.12.0.rc0, 2.11.4
    • Affects Version/s: 2.11.3
    • Component/s: Connections
    • None
    • Fully Compatible

      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:

      Unable to find source-code formatter for language: diff. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
      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>
      

            Assignee:
            oleg.pudeyev@mongodb.com Oleg Pudeyev (Inactive)
            Reporter:
            alex.bevilacqua@mongodb.com Alex Bevilacqua
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: