我现在使用 Netty 作为我的后端 Web 服务,使用 MongoDB 作为我的数据库。
一开始,我很高兴MongoDB和Netty结合的高性能。
但最近我检查了 MongoDB 日志(和 db.serverStatus() 命令),发现了一个非常非常严重的问题:每次 Netty 处理带有 messageReceived 的 RESTful HttpRequest 时,都会占用一个可用的 MongoDB 连接并且即使我关闭 Netty 也不会释放渠道。
而且由于 MongoDB 提供的并发连接只有 20,000 个,所以每个连接都非常宝贵。如果我不能解决这个问题,我的服务会在收到超过 20000 个请求后崩溃。
我还在单例 MongoDB 上做了一个测试用例,我发现在没有 Netty 的情况下,一切正常(一个不断查询 MongoDB 的 Timer 程序)。即使我一次执行超过 5 个查询,也只会建立一个连接。
Netty框架下如何释放MongoDB中的连接?似乎问题来自Netty Framework。我一直在寻找这个问题的解决方案。
我还在 MongoDB 连接字符串中添加了“connectTimeoutMS=10000&socketTimeoutMS=10000”,但似乎没用。在我关闭整个程序之前,连接永远不会结束。
网络实现:
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);
}
单例 MongoDB 实现:
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;
}
}
....
}
我查询/更新 MongoDB 的方式:
MongoDbCore.getInstance().updateChannelStatusByChannelId(123, "abc");
谢谢!!