У mongoDB есть проблемы с переподключением или я делаю это неправильно?

Я использую nodejs и mongoDB - и у меня есть некоторые проблемы с подключением.

Ну собственно "разбуди" вопросы! Он отлично соединяется - очень быстрый, и я в целом доволен результатами.

Моя проблема: если я не использую соединение какое-то время (я говорю время, потому что период времени колеблется 5+ минут), оно, кажется, застопорилось. Я не получаю события разъединения, это просто зависает.

В конце концов я получаю ответ типа Ошибка: не удалось подключиться к [ * .mongolab.com: * ] - ( * = маскированные значения)

Быстрый перезапуск приложения, и соединение снова здорово. Иногда, если я не перезагружаю приложение, я могу обновить его, и оно счастливо подключается.

Вот почему я думаю, что это "пробуждение" вопросов.

Грубый набросок кода:

Я не включил код - я не думаю, что он нужен. Это работает (кроме пропадания соединения)

Вещи, чтобы отметить: есть только одно "соединение" - я никогда не закрываю это. Я никогда не открываю.

Я использую мангуста, сокетио.

/* constants */

var mongoConnect = 'myworkingconnectionstring-includingDBname';


/* includes */

/* settings */

/* Schema */

var db = mongoose.connect(mongoConnect);

    /* Socketio */

io.configure(function (){
    io.set('authorization', function (handshakeData, callback) {

    });
});

io.sockets.on('connection', function (socket) {

});//sockets

io.sockets.on('disconnect', function(socket) {
    console.log('socket disconnection')
});

/* The Routing */

app.post('/login', function(req, res){  

});

app.get('/invited', function(req, res){

});

app.get('/', function(req, res){

});

app.get('/logout', function(req, res){

});

app.get('/error', function(req, res){

});

server.listen(port);
console.log('Listening on port '+port);

db.connection.on('error', function(err) {
    console.log("DB connection Error: "+err);
});
db.connection.on('open', function() {
    console.log("DB connected");
});
db.connection.on('close', function(str) {
    console.log("DB disconnected: "+str);
});

Я пробовал различные конфигурации здесь, например, открывать и закрывать все время - хотя, я полагаю, общий консенсус заключается в том, чтобы делать то же, что и я, с одним открытием, оборачивающим лот.??

Я попробовал тестер подключений, который продолжает проверять состояние подключения... даже если кажется, что все в порядке - проблема все еще возникает.

У меня была эта проблема с первого дня. Я всегда принимал MongoDB вместе с MongoLab. Проблема кажется хуже на localhost. Но у меня все еще есть проблема на Azure и теперь nodejit.su.

Как это происходит везде - это должен быть я, MongoDB или mongolab.

Между прочим, у меня был подобный опыт с драйвером PHP тоже. (чтобы подтвердить это на nodejs, хотя)

Это было бы здорово для некоторой помощи - даже если кто-то просто говорит "это нормально"

заранее спасибо

обкрадывать

6 ответов

Решение

Спасибо всем за помощь, ребята, мне удалось решить эту проблему как на локальном хосте, так и на развернутом сервере.

Вот мой теперь работающий код подключения:

var MONGO = {
    username: "username",
    password: "pa55W0rd!",
    server: '******.mongolab.com',
    port: '*****',
    db: 'dbname',
    connectionString: function(){
        return 'mongodb://'+this.username+':'+this.password+'@'+this.server+':'+this.port+'/'+this.db;
    },
    options: {
        server:{
            auto_reconnect: true,
            socketOptions:{
                connectTimeoutMS:3600000,
                keepAlive:3600000,
                socketTimeoutMS:3600000
            }
        }
    }
};

var db = mongoose.createConnection(MONGO.connectionString(), MONGO.options);

db.on('error', function(err) {
    console.log("DB connection Error: "+err);
});
db.on('open', function() {
    console.log("DB connected");
});
db.on('close', function(str) {
    console.log("DB disconnected: "+str);
});

Я думаю, что самым большим изменением было использование "createConnection" вместо "connect" - я использовал это раньше, но, возможно, варианты помогают сейчас. Эта статья очень помогла http://journal.michaelahlers.org/2012/12/building-with-nodejs-persistence.html

Если честно, я не слишком уверен в том, почему я добавил эти опции - как упомянул @jareed, я также обнаружил, что некоторые люди добились успеха с "MaxConnectionIdleTime" - но, насколько я вижу, драйвер javascript этого не делает есть такая опция: это была моя попытка повторить поведение.

Пока все хорошо - надеюсь, это кому-нибудь поможет.

ОБНОВЛЕНИЕ: 18 апреля 2013 г. обратите внимание, это второе приложение с другой настройкой

Теперь я подумал, что решил эту проблему, но проблема возникла, потому что недавно он снова оказался в другом приложении - с тем же кодом подключения. Смущенный!!!

Однако установка была немного другой...

Это новое приложение было запущено в окне Windows с помощью IISNode. Первоначально я не считал это значительным.

Я читал, что в Azure (@jareed), возможно, были некоторые проблемы с mongo, поэтому я переместил БД в AWS, но проблема осталась.

Так что я снова начал играть с этим объектом параметров, много читая о нем. Пришли к такому выводу:

options: {
    server:{
        auto_reconnect: true,
        poolSize: 10,
        socketOptions:{
            keepAlive: 1
        }
    },
    db: {
        numberOfRetries: 10,
        retryMiliSeconds: 1000
    }
}

Это было немного более образованным, чем мой первоначальный вариант, который я утверждаю. Однако - это все еще не хорошо.

Теперь по какой-то причине мне пришлось снять с этого окна Windows (что-то связанное с модулем, который не компилируется на нем) - было легче двигаться, чем потратить еще одну неделю, пытаясь заставить его работать.

Поэтому я переместил свое приложение в nodejitsu. Низкий и вот моя связь осталась в живых! Woo!

Так…. что это значит... понятия не имею! Что я знаю, так это то, что эти варианты работают на Nodejitsu… для меня.

Я считаю, что IISNode использует какой-то сценарий "навсегда" для поддержки приложения. Теперь, чтобы быть справедливым, приложение не падает, чтобы это сработало, но я думаю, что должен быть какой-то "цикл приложения", который постоянно обновляется - вот как он может выполнять непрерывное развертывание (код ftp вверх, нет необходимости перезапустите приложение) - возможно, это фактор; но я просто догадываюсь сейчас.

Конечно, теперь все это означает, что это не решено. Это все еще не решено. Это просто решено для меня в моей настройке.

ОБНОВЛЕНИЕ: наша статья поддержки по этой теме (по сути, копия этого поста) перенесена в наш документ по устранению неполадок с подключением.

Известна проблема, заключающаяся в том, что в сети IaaS Azure время простоя составляет примерно тринадцать минут (получено эмпирически). Мы работаем с Azure, чтобы выяснить, не можем ли мы сделать вещи более удобными для пользователя, но в то же время другие добились успеха, настроив свои параметры драйвера для решения этой проблемы.

Максимальное время простоя соединения

Наиболее эффективный обходной путь, который мы нашли при работе с Azure и нашими клиентами, - это установить максимальное время простоя соединения ниже четырех минут. Идея состоит в том, чтобы драйвер перезапустил незанятые соединения до того, как брандмауэр вызовет проблему. Например, один клиент, который использует драйвер C#, установил MongoDefaults.MaxConnectionIdleTime до одной минуты, и это прояснило их проблемы.

MongoDefaults.MaxConnectionIdleTime = TimeSpan.FromMinutes(1);

Сам код приложения не изменился, но теперь за кулисами драйвер агрессивно перезапускает простаивающие соединения. Результат можно увидеть и в журналах сервера: много оттока соединений во время периодов простоя в приложении.

Подробнее об этом подходе рассказано в связанном моно-пользовательском потоке SocketException с использованием драйвера C# в Azure.

Keepalive

Вы также можете обойти эту проблему, сделав ваши соединения менее простыми с некоторой поддержкой активности. Это немного сложно реализовать, если ваш драйвер не поддерживает его из коробки, обычно используя преимущества TCP Keepalive. Если вам нужно свернуть свое собственное, убедитесь, что каждые пару минут вынимаете каждое простаивающее соединение из пула и выполняете простую и дешевую команду, возможно, ping.

Обработка разъединений

Отключение может происходить время от времени даже без агрессивной настройки брандмауэра. Прежде чем вы начнете производство, вы должны быть уверены, что правильно с ними справились.

Сначала обязательно включите автоматическое переподключение. Как это сделать, зависит от драйвера к драйверу, но когда драйвер обнаруживает, что операция завершилась неудачно из-за плохого соединения, автоматическое переподключение указывает водителю попытаться переподключиться.

Но это не полностью решает проблему. У вас все еще есть проблема, что делать с неудачной операцией, которая вызвала переподключение. Автоматическое переподключение не повторяет автоматически неудачные операции. Это было бы опасно, особенно для писем. Поэтому обычно выдается исключение, и приложение просят его обработать. Часто повторная попытка чтения не составляет труда. Но повторные записи должны быть тщательно продуманы.

Сессия оболочки Монго ниже демонстрирует проблему. В оболочке Монго по умолчанию включено автоматическое переподключение. Я вставляю документ в коллекцию с именем stuff затем найдите все документы в этой коллекции. Затем я установил таймер на тридцать минут и снова попытался найти ту же самую находку. Это не удалось, но оболочка автоматически переподключилась, и когда я сразу же повторил попытку поиска, все заработало, как и ожидалось.

% mongo ds012345.mongolab.com:12345/mydatabase -u *** -p *** 
MongoDB shell version: 2.2.2 
connecting to: ds012345.mongolab.com:12345/mydatabase 
> db.stuff.insert({}) 
> db.stuff.find() 
{ "_id" : ObjectId("50f9b77c27b2e67041fd2245") } 
> db.stuff.find() 
Fri Jan 18 13:29:28 Socket recv() errno:60 Operation timed out 192.168.1.111:12345 
Fri Jan 18 13:29:28 SocketException: remote: 192.168.1.111:12345 error: 9001 socket exception [1] server [192.168.1.111:12345] 
Fri Jan 18 13:29:28 DBClientCursor::init call() failed 
Fri Jan 18 13:29:28 query failed : mydatabase.stuff {} to: ds012345.mongolab.com:12345 
Error: error doing query: failed 
Fri Jan 18 13:29:28 trying reconnect to ds012345.mongolab.com:12345 
Fri Jan 18 13:29:28 reconnect ds012345.mongolab.com:12345 ok 
> db.stuff.find() 
{ "_id" : ObjectId("50f9b77c27b2e67041fd2245") }

Мы здесь, чтобы помочь

Конечно, если у вас есть какие-либо вопросы, пожалуйста свяжитесь с нами по адресу support@mongolab.com. Мы здесь, чтобы помочь.

Несколько рекомендаций для людей, у которых все еще есть эта проблема:

  1. Убедитесь, что вы используете последнюю версию клиента mongodb для node.js. Я заметил значительные улучшения в этой области при переходе с v1.2.x на v1.3.10 (последний на сегодня)

  2. Вы можете передать объект параметров в MongoClient.connect. При подключении из Azure к MongoLab у меня работали следующие параметры:

    options = {db: {}, сервер: {auto_reconnect: true, socketOptions: {keepAlive: 1}}, replSet: {}, mongos: {}};

    MongoClient.connect (dbUrl, options, function (err, dbConn) {// ваш код});

  3. Посмотрите этот другой ответ, в котором я опишу, как обрабатывать событие "close", которое кажется более надежным. /questions/355623/kak-ubeditsya-chto-nodejs-prodolzhaet-rabotat-posle-razryiva-soedineniya-s-monogdb/355653#355653

Включить auto_reconnectServer вариант как этот:

var db = mongoose.connect(mongoConnect, {server: {auto_reconnect: true}});

Соединение, которое вы открываете здесь, на самом деле представляет собой пул из 5 соединений (по умолчанию), поэтому вы можете просто подключиться и оставить его открытым. Я предполагаю, что вы периодически теряете связь с mongolab, и ваши соединения умирают, когда это происходит. Надеюсь, что позволит auto_reconnect решает это.

Увеличение таймаутов может помочь.

  • "socketTimeoutMS": сколько времени может занять отправка или получение в сокете до истечения времени ожидания.
  • "wTimeoutMS": он контролирует, сколько миллисекунд сервер ожидает, пока проблема записи не будет выполнена.
  • "connectTimeoutMS": сколько времени может потребоваться для открытия соединения до истечения времени ожидания в миллисекундах.

    $ m = новый MongoClient("mongodb://127.0.0.1:27017", массив ("connect"=>TRUE, "connectTimeoutMS"=>10, "socketTimeoutMS"=>10, "wTimeoutMS"=>10));

        $db= $m->mydb;
        $coll = $db->testData;
        $coll->insert($paramArr);
    

У меня была похожая проблема, когда я периодически отключался от MongoDB. Делать две вещи исправили это:

  1. Убедитесь, что ваш компьютер никогда не спит (это убьет ваше сетевое соединение).
  2. Обходите ваш роутер / брандмауэр (или настройте его правильно, что я пока не выяснил, как это сделать).
Другие вопросы по тегам