Сейчас я использую Netty в качестве внутреннего веб-сервиса и MongoDB в качестве базы данных.
Сначала я очень доволен высокой производительностью комбинации MongoDB и Netty.
Но недавно Я проверил журналы MongoDB (и команду db.serverStatus()) и обнаружил очень и очень серьезную проблему: каждый раз, когда Netty обрабатывает RESTful HttpRequest с messageReceived, берется одно доступное соединение MongoDB и никогда не освобождается, даже если я закрываю канал Netty.
А поскольку MongoDB обеспечивает всего 20 000 одновременных подключений, каждое подключение очень ценно. Если я не смогу решить эту проблему, мой сервис рухнет после получения более 20000 запросов.
Я также сделал тестовый пример на одноэлементной MongoDB, я обнаружил, что в ситуации без Netty все работает нормально (программа Timer продолжая запрашивать MongoDB). Принимается только одно соединение, даже если я выполняю более 5 запросов одновременно.
Как я могу освободить соединение в MongoDB под Netty Framework? Похоже, проблема возникла из-за Netty Framework. Я долго искал решение этой проблемы.
Я также добавил «connectTimeoutMS=10000&socketTimeoutMS=10000» в строку подключения MongoDB, но это кажется бесполезным. Соединение никогда не прервется, пока я не закрою всю программу.
Нетти импл:
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");
Спасибо!!