Netty HTTP + MongoDB: неограниченное увеличение количества соединений


Сейчас я использую 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");

Спасибо!!


person Cheng    schedule 07.06.2013    source источник
comment
Действительно ли объект Mongo(Client) в вашем приложении Netty рассматривается как синглтон? Вы не должны создавать более одного из них. Также обратите внимание, что драйвер Java фактически использует все соединения, которые ему разрешены. Если для параметра максимального количества подключений в MongoOptions установлено относительно низкое значение (10-100), вы сможете увидеть, ограничено ли количество подключений этим числом (и, следовательно, вы действительно используете только один экземпляр MongoClient)   -  person Remon van Vliet    schedule 07.06.2013
comment
Я добавил способ реализации singleton MongoDB. Раньше я запускал MongoDB для maxConn=5 для эксперимента и после открытия более 5 программ. Он разбился. Новое подключение не принимается.   -  person Cheng    schedule 07.06.2013
comment
Спасибо за вашу помощь!! Я провожу эксперимент: перенастраиваю --maxConn на 10 и имитирую HTTP-публикацию каждые 2 секунды. Я нашел после 15 сообщений HTTP. Приходите к 14 успехам, 1 отказу (все соединения принудительно сбрасываются). Это из-за несовместимости Нетти? Я как-то сожалею об использовании MongoDB.   -  person Cheng    schedule 07.06.2013


Ответы (1)


Позже я переношу свой код в JSP/Servlet. Все работает нормально. Я почти на 100% уверен, что проблема связана с Netty и несовместимостью между Netty и MongoDB. Независимо от того, сколько сообщений я вызывал, счетчик соединений остается равным 1.

person Cheng    schedule 08.06.2013