[JAVA-756] SSL Connection Pool Threading - Stale Connections Created: 09/Feb/13  Updated: 25/Jun/13  Resolved: 10/Feb/13

Status: Closed
Project: Java Driver
Component/s: Connection Management
Affects Version/s: 2.10.1
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Torben Werner Assignee: Unassigned
Resolution: Cannot Reproduce Votes: 0
Labels: connections, ssl
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

java version "1.7.0_11"
Java(TM) SE Runtime Environment (build 1.7.0_11-b21)
Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode)



 Description   

Client is initialized as follows:

String dbHost = SSL_SERVER_ADDRESS;
int dbPort = SSL_SERVER_PORT;
MongoClientOptions o = new MongoClientOptions.Builder()
.socketFactory(SSLSocketFactory.getDefault())
.build();
mongo = new MongoClient(new ServerAddress(dbHost, dbPort), o);

The mongo object is stored as a singleton and is accessed by other threads.

Getting a collection, saving and inserting while in the thread that initialized the client is fine. The problem occurs when the client is accessed by other threads. When another thread attempts to get a collection as follows:

db.getCollection("testCollection");

I receive the following exception:

Caused by: com.mongodb.MongoException$Network: can't call something :

{HOST_NAME}

/

{HOST_IP_ADDRESS}

:

{PORT}

/

{DBNAME}

at com.mongodb.DBTCPConnector.innerCall(DBTCPConnector.java:295) ~[mongo-java-driver-2.10.1.jar:na]
at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:257) ~[mongo-java-driver-2.10.1.jar:na]
at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:310) ~[mongo-java-driver-2.10.1.jar:na]
at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:295) ~[mongo-java-driver-2.10.1.jar:na]
at com.mongodb.DBCursor._check(DBCursor.java:368) ~[mongo-java-driver-2.10.1.jar:na]
at com.mongodb.DBCursor._hasNext(DBCursor.java:459) ~[mongo-java-driver-2.10.1.jar:na]
Caused by: java.io.EOFException: null
at org.bson.io.Bits.readFully(Bits.java:48) ~[mongo-java-driver-2.10.1.jar:na]
at org.bson.io.Bits.readFully(Bits.java:33) ~[mongo-java-driver-2.10.1.jar:na]
at org.bson.io.Bits.readFully(Bits.java:28) ~[mongo-java-driver-2.10.1.jar:na]
at com.mongodb.Response.<init>(Response.java:40) ~[mongo-java-driver-2.10.1.jar:na]
at com.mongodb.DBPort.go(DBPort.java:124) ~[mongo-java-driver-2.10.1.jar:na]
at com.mongodb.DBPort.go(DBPort.java:88) ~[mongo-java-driver-2.10.1.jar:na]

This exception is generated by any threads that attempt to access a collection in this manner until the number of attempts have exceeded the connection pool size. After this point the exception no longer occur.

This problem does not occur when a non-SSL connection is made in the following way:

MongoClientOptions o = new MongoClientOptions.Builder()
.build();
mongo = new MongoClient(new ServerAddress(NON_SSL_DB_HOST, DB_PORT), o);

This leads me to believe that the issue is specific to SSL connections.

I have also found the following workaround prevents the exceptions from occurring when other threads attempt to access a collection:

String dbHost = SSL_SERVER_ADDRESS;
int dbPort = SSL_SERVER_PORT;
MongoClientOptions o = new MongoClientOptions.Builder()
.socketFactory(SSLSocketFactory.getDefault())
.build();
mongo = new MongoClient(new ServerAddress(dbHost, dbPort), o);
for(int i = 0 ; i < mongo.getMongoOptions().getConnectionsPerHost(); i++){
mongo.getDB(dbName).getCollection("testCollection");
}

Note the above code is run within the same thread that initializes the client. However, if the collections are cycled through by the initializing thread as in the above code, other threads no longer generate exceptions when accessing a collection.



 Comments   
Comment by Jeffrey Yemin [ 10/Feb/13 ]

OK, thanks for the report. Please re-open if you see it again.

Comment by Torben Werner [ 09/Feb/13 ]

For completeness, here is the test harness:

public static void main(String[] args) throws UnknownHostException, InterruptedException{
		final String dbHost = SSL_DB_HOST_ADDRESS;
    	final int dbPort = SSL_DB_HOST_PORT;
    	MongoClientOptions o = new MongoClientOptions.Builder()
    	.socketFactory(SSLSocketFactory.getDefault())
    	.build();
    	final Mongo mongo = new MongoClient(new ServerAddress(dbHost, dbPort), o);    	
    	final AtomicInteger exceptionCount = new AtomicInteger(0);
    	
    	final int numberOfThreads = mongo.getMongoOptions().getConnectionsPerHost() + 5;
    	Thread[] threadPool = new Thread[numberOfThreads];
    	final DB db = mongo.getDB(DB_NAME);
    	db.authenticate(DB_USERNAME, DB_PASSWORD.toCharArray());
    	
    	Thread.sleep(500);
    	
    	for(int i = 0 ; i < numberOfThreads; i++){
    		Thread.sleep(100);
    		threadPool[i] = new Thread(new Runnable(){
				@Override
				public void run() {
					try{						
						db.getCollection("testCollection");
					}catch(MongoException e){
						System.out.println("Encountered mongo exception number[" +  exceptionCount.incrementAndGet() + "]");
					}
				}
    		});
    		threadPool[i].start();
    	}
    	
    	// Wait for all threads to complete
    	for(int i = 0; i < threadPool.length; i++){
    		try {
				Thread thread = threadPool[i];
				thread.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
    	}
    	
    	System.out.println("TEST HARNESS FINISHED");
    	System.out.println("There were " + exceptionCount.get() + " exceptions encountered.");
	}

Comment by Torben Werner [ 09/Feb/13 ]

I am no longer able to reproduce this issue. Not sure why as it was reliably reproducible up until just now. As I cannot reproduce this anymore I suspect this issue may have actually been some other connection issue.

This issue can probably be closed...

Generated at Thu Feb 08 08:53:00 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.