Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-560

Mongo and Mongo.Holder internal pooling don't tolerate IP address changes

    • Type: Icon: Bug Bug
    • Resolution: Duplicate
    • Priority: Icon: Critical - P2 Critical - P2
    • None
    • Affects Version/s: 2.7.2
    • Component/s: Connection Management
    • None
    • Environment:
      Java 1.6 on Ubuntu and Mac OS X, MongoDB 2.0.4 for Ubuntu and Mac OS X, 64-bit, running in auth mode

      For singleton Mongos and Mongos managed by Mongo.Holders a change in a server IP address causes errors when trying to use the objects to make further queries. There seems to be some code in place to refresh pooled replica set connections, though I haven't tested that it works.

      Note that in both cases we are using MongoURIs to connect.

      To replicate we added the IpTest class to our app server (code below), fronted by a simple JSP that calls findStuff() with the result of getStuffCollection on each of the static member variables from the Mongo URI string down to the DBCollection itself. We then:

      1. Started the app
      2. Hit the JSP page (all methods passed without error)
      3. Changed the IP address of the machine (in this case by switching to another wireless network)
      4. Hit the JSP page

      All but the Mongo URI and Mongo URI string failed with the same operation timeout exception. Since IP addresses change fairly frequently in the cloud we have now started running into problems in production where we frequently need to restart the application process as a result of this.

      package com.company.iptest;
      
      import com.mongodb.BasicDBObject;
      import com.mongodb.DB;
      import com.mongodb.DBCollection;
      import com.mongodb.DBObject;
      import com.mongodb.Mongo;
      import com.mongodb.MongoURI;
      import com.mongodb.ServerAddress;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      import java.net.UnknownHostException;
      
      public class IpTest {
      
          private static final Logger log = LoggerFactory.getLogger(IpTest.class);
      
          public static final String _mongoUriString = "mongodb://username:password@localhost:27017/database";
      
          public static MongoURI _mongoUri;
          public static Mongo.Holder _mongoHolder;
          public static Mongo _mongo;
          public static DB _db;
          public static DBCollection _collection;
      
          static {
              try {
                  _mongoUri = new MongoURI(_mongoUriString);
                  _mongoHolder = new Mongo.Holder();
                  _mongo = _mongoHolder.connect(_mongoUri);
                  _mongo.getDB(_mongoUri.getDatabase()).authenticate(_mongoUri.getUsername(), _mongoUri.getPassword());
                  _db = _mongo.getDB("database");
                  _collection = _db.getCollection("stuff");
              } catch ( Exception e ) {
                  log.error("Unexpected exception", e);
              }
          }
      
          public static DBCollection getStuffCollection ( String mongoUriString )
                  throws UnknownHostException {
              return getStuffCollection(new MongoURI(mongoUriString));
          }
      
          public static DBCollection getStuffCollection ( MongoURI mongoUri )
                  throws UnknownHostException {
              DBCollection c = getStuffCollection(new Mongo(mongoUri));
              DB db = c.getDB();
              if ( !db.isAuthenticated() ) {
                  db = db.getMongo().getDB(mongoUri.getDatabase());
                  db.authenticate(mongoUri.getUsername(), mongoUri.getPassword());
              }
              return c;
          }
      
          public static DBCollection getStuffCollection ( Mongo.Holder mongoHolder )
                  throws UnknownHostException {
              return getStuffCollection(mongoHolder.connect(new MongoURI(_mongoUriString)));
          }
      
          public static DBCollection getStuffCollection ( Mongo mongo ) {
              return getStuffCollection(mongo.getDB("database"));
          }
      
          public static DBCollection getStuffCollection ( DB db ) {
              return db.getCollection("stuff");
          }
      
          public static DBObject findStuff ( DBCollection stuffCollection ) {
              return stuffCollection.findOne();
          }
      
      }
      
      Caused by: com.mongodb.MongoException$Network: can't call something : mymac.local/10.0.0.5:27017/database
      	at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:227)
      	at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:305)
      	at com.mongodb.DBCollection.findOne(DBCollection.java:332)
      	at com.mongodb.DBCollection.findOne(DBCollection.java:318)
              at [ ... application code ... ]
      	... 64 more
      Caused by: java.net.SocketException: Operation timed out
      	at java.net.SocketInputStream.socketRead0(Native Method)
      	at java.net.SocketInputStream.read(SocketInputStream.java:129)
      	at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
      	at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
      	at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
      	at org.bson.io.Bits.readFully(Bits.java:35)
      	at org.bson.io.Bits.readFully(Bits.java:28)
      	at com.mongodb.Response.<init>(Response.java:39)
      	at com.mongodb.DBPort.go(DBPort.java:128)
      	at com.mongodb.DBPort.call(DBPort.java:79)
      	at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:218)
      	... 69 more
      

            Assignee:
            Unassigned Unassigned
            Reporter:
            jared Jared D. Cottrell
            Votes:
            9 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: