Reputation: 1061
I have a java application which uses around 3000 reusable threads which is always running and processing items from a queue. I use MongoDB for my data storage and every time I run it it works perfectly for around 40 minutes, after that Mongo DB Object start returning Nullpointer Exception for queries. At first I suspected that it might be due to connections being lost but as you can see in the Google monitoring graph the connections are still open, but there is a significant decrease in number of Mongo queries. Is there anything Im missing here?
My MongoDB class is like this:
public class MongoDB {
private static MongoClient mongoClient;
private static MongoClient initMongoClient() {
ServerAddress server = new ServerAddress("X.X.X.X");
MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
builder.threadsAllowedToBlockForConnectionMultiplier(50000);
builder.socketKeepAlive(true);
builder.connectionsPerHost(10000);
builder.minConnectionsPerHost(2500);
MongoClientOptions options = builder.build();
MongoClient mc = new MongoClient(server, options);
mongoClient = mc;
return mc;
}
public static MongoClient getMongoClient() {
if(mongoClient == null) {
mongoClient = initMongoClient();
}
return mongoClient;
}
public static DB getDb() {
DB db;
MongoClient mc;
try {
mc = getMongoClient();
mc.getDatabaseNames();
} catch(MongoException e) {
mc = initMongoClient();
}
db = mc.getDB("tina");
return db;
}
}
Upvotes: 4
Views: 1284
Reputation: 161
You should switch to Morphia! https://github.com/mongodb/morphia
Use the factory pattern to produce a single Mongo instance and tie it to a Morphia Datastore object. You can then use the Datastore object to interface with your MongoDB.
public class DatastoreFactory {
private static Datastore ds;
public static Datastore getDatastore() {
//Lazy load the datastore
if(ds == null) {
try {
Morphia morphia = new Morphia();
ds = morphia.createDatastore(
new MongoClient("server", port, "database"));
//... Other datastore options
} catch(Exception e) {
// Handle it
}
}
return ds;
}
Then wherever you need your MongoDB instance you simple use the Datastore object and get it from the factory
Datastore ds = DatastoreFactory.getDatastore();
You could also use CDI to inject the datastore if that's what you're into
@Singleton
public class DatastoreFactory {
private Datastore ds;
@Produces
public Datastore getDatastore() {
//Lazy load the datastore
if(ds == null) {
try {
Morphia morphia = new Morphia();
ds = morphia.createDatastore(
new MongoClient("server", port, "database"));
//... Other datastore options
} catch(Exception e) {
// Handle it
}
}
return ds;
}
Then inject it like so
@Inject
Datastore ds;
BONUS
To further decouple your code from MongoDB, it would be proper design to create Data Access Objects (DAO) to access your database which will contain the Morphia Datastore object. Your DAO will have the methods you wish to use on the database (get, create, save, delete). This way if you decide to move away from MongoDB you will only have to change the DAO object and not all of your code!
Upvotes: 2