I'm now using Netty as my backend webservice and MongoDB as my database.
At first, I'm very glad with the high performance of the combination of MongoDB and Netty.
But recently I checked the MongoDB logs(and db.serverStatus() command) and found a very very serious issue: Every time Netty handles a RESTful HttpRequest with messageReceived, one available connection of MongoDB is taken and never release even if I close the Netty Channel.
And since there're only 20,000 concurrent connections that MongoDB provide, every connection is very precious. If I can't solve this problem, my service will crash after receiving more than 20000 requests.
I also did an test case on singleton MongoDB, I found that under the situation without Netty, everything works fine (A Timer program keeping to query MongoDB). There's only one connection taken even if I execute more than 5 queries at a time.
How can I release the connection in MongoDB under Netty Framework? Seem like the problem come from Netty Framework.
I've been seeking the solution to this issue for a long time.
I also added "connectTimeoutMS=10000&socketTimeoutMS=10000" to the MongoDB connection string, but seem useless. The connection will never end until I close the whole program.
Netty impl:
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
HttpResponse httpResponse = null;
HttpRequest request = (HttpRequest) e.getMessage();
(... Query "Singleton([the way I implement][1])" MongoDB ...)
httpResponse.setContent(responseBuffer);
httpResponse.addHeader(HttpHeaders.Names.CONTENT_LENGTH,
responseBuffer.readableBytes());
ChannelFuture future = ctx.getChannel().write(httpResponse);
future.addListener(ChannelFutureListener.CLOSE);
}
Singleton MongoDB impl:
public class MongoDbCore {
private static MongoDbCore mINSTANCE = null;
private static Logger logger = Logger
.getLogger(MongoDbCore.class.getName());
private static DB db;
private static MongoClient mongoClient;
private MongoDbCore() {
}
public static MongoDbCore getInstance() {
if (mINSTANCE == null) {
mINSTANCE = new MongoDbCore();
try {
String connString = "mongodb://"
+ Configs.MongoDB.DB_HOST
+ ":"
+ Configs.MongoDB.DB_PORT
+ "/?connectTimeoutMS=10000&socketTimeoutMS=10000";
mongoClient = new MongoClient(new MongoClientURI(connString));
logger.info("ConnectionString=" + connString);
db = mongoClient.getDB(Configs.MongoDB.MY_DB);
} catch (UnknownHostException ex) {
logger.info("Error while initialing the MongoDB.");
}
}
return mINSTANCE;
}
public static DB getDb() {
return db;
}
public boolean updateChannelStatusByChannelId(Integer tid, String status) {
try {
DBCollection coll = db.getCollection(Configs.MongoDB.DB.TABLE_REGS);
BasicDBObject newDocument = new BasicDBObject();
newDocument.append("$set",
new BasicDBObject().append("status", status));
BasicDBObject searchQuery = new BasicDBObject().append("tid", tid);
coll.update(searchQuery, newDocument, false, false,
WriteConcern.SAFE);
return true;
} catch (Exception ex) {
return false;
}
}
....
}
The way I query/update MongoDB:
MongoDbCore.getInstance().updateChannelStatusByChannelId(123, "abc");
Thanks!!