Подтвердить что ты не робот

Опция Mongoose autoReconnect

Я пытаюсь настроить функцию автоматического пересоединения MongoDB через Mongoose. Каждый способ, которым я пытался передать этот параметр, не имел никакого эффекта, или, по крайней мере, событие reconnected не испускается.

Что я пробовал:

mongoose.createConnection("mongodb://localhost:27017/test", { auto_reconnect: true });
mongoose.createConnection("mongodb://localhost:27017/test", { autoReconnect: true });
mongoose.createConnection("mongodb://localhost:27017/test", { server: { auto_reconnect: true } });
mongoose.createConnection("mongodb://localhost:27017/test", { server: { autoReconnect: true } });

Если одно из них верно, событие reconnected должно быть запущено, и сообщение должно быть зарегистрировано в консоли, однако этого никогда не произойдет.

Если перед пересоединением существует задержка, кто-нибудь знает, как его настроить?

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

Для всех, кто это изучает, посмотрите этот и этот вопрос в репозитории mongoose.

4b9b3361

Ответ 1

У меня был тот же вопрос, что и вы, и решение robertklep тоже не работало для меня. Я обнаружил, что когда служба MongoDB остановлена, запускается событие ошибки, но connection.readyState все еще 1 (подключен). Возможно, поэтому он не подключался автоматически.

Это то, что у меня есть сейчас:

  var db = mongoose.connection;

  db.on('connecting', function() {
    console.log('connecting to MongoDB...');
  });

  db.on('error', function(error) {
    console.error('Error in MongoDb connection: ' + error);
    mongoose.disconnect();
  });
  db.on('connected', function() {
    console.log('MongoDB connected!');
  });
  db.once('open', function() {
    console.log('MongoDB connection opened!');
  });
  db.on('reconnected', function () {
    console.log('MongoDB reconnected!');
  });
  db.on('disconnected', function() {
    console.log('MongoDB disconnected!');
    mongoose.connect(dbURI, {server:{auto_reconnect:true}});
  });
  mongoose.connect(dbURI, {server:{auto_reconnect:true}});

Ответ 2

Сорвал с http://bites.goodeggs.com/posts/reconnecting-to-mongodb-when-mongoose-connect-fails-at-startup/

Это сработало для меня:

var mongoose = require('mongoose')
var mongoUrl = "mongodb://localhost:27017/test"

var connectWithRetry = function() {
  return mongoose.connect(mongoUrl, function(err) {
    if (err) {
      console.error('Failed to connect to mongo on startup - retrying in 5 sec', err);
      setTimeout(connectWithRetry, 5000);
    }
  });
};
connectWithRetry();

Ответ 3

В последнее время я исследую автоподключение с помощью MongoDB var Mongoose. Здесь возникает одна проблема: при вызове mongoose.connect внутри обработчика события disconnected он вызывает бесконечный цикл. Почему сигнал SIGINT блокируется при автоподключении мангуста.

Одно решение проблемы может заключаться в том, что mongoose.connect() вызывается только тогда, когда нет связи с MongoDB. Флаг auto_reconnect может автоматически переключать mongoose с MongoDB. Вот фрагменты кода.

var mongoose = require('mongoose');

var isConnectedBefore = false;
var connect = function() {
    mongoose.connect('mongodb://localhost/' + + 'test_dev', {server: { auto_reconnect: true }});
};
connect();

mongoose.connection.on('error', function() {
    console.log('Could not connect to MongoDB');
});

mongoose.connection.on('disconnected', function(){
    console.log('Lost MongoDB connection...');
    if (!isConnectedBefore)
        connect();
});
mongoose.connection.on('connected', function() {
    isConnectedBefore = true;
    console.log('Connection established to MongoDB');
});

mongoose.connection.on('reconnected', function() {
    console.log('Reconnected to MongoDB');
});

// Close the Mongoose connection, when receiving SIGINT
process.on('SIGINT', function() {
    mongoose.connection.close(function () {
        console.log('Force to close the MongoDB conection');
        process.exit(0);
    });
});

Ответ 4

Просто ради потомков, так как большинство этих ответов старые, вам не нужно больше заниматься этой проблемой, так как она теперь запекается в драйвере nodejs mongodb. Цитировать kdmon:

... переподключение теперь запекается в мангусте и включено по умолчанию. Но может быть полезно знать, что Mongoose по умолчанию будет пытаться переподключиться только в течение 30 секунд, а затем сдаться. Установите параметр server.reconnectTries, чтобы увеличить количество попыток повторного подключения mongoose. Например, вы можете указать mongoose никогда не прекращать попытки повторного подключения следующим образом:

mongoose.connect(uri, { server: { reconnectTries: Number.MAX_VALUE } });

See connection docs и server options defaults for details

Ответ 5

Удостоверьтесь, что мангуста - это единственный способ, которым вы подключаетесь к Монго. В моем случае я использую connect-mongo для хранения сеансов в Express, но у него нет auto_reconnect, установленного по умолчанию по умолчанию, начиная с v0.4.0.

Ответ 6

Ниже приведено улучшение ответа Клайва, устанавливающего минимум 5 секунд между попытками подключения.

var db = mongoose.connection;
var lastReconnectAttempt; //saves the timestamp of the last reconnect attempt
db.on('error', function(error) {
    console.error('Error in MongoDb connection: ' + error);
    mongoose.disconnect();
});
db.on('disconnected', function() {
    console.log('MongoDB disconnected!');
    var now = new Date().getTime();
    // check if the last reconnection attempt was too early
    if (lastReconnectAttempt && now-lastReconnectAttempt<5000) {
        // if it does, delay the next attempt
        var delay = 5000-(now-lastReconnectAttempt);
        console.log('reconnecting to MongoDB in ' + delay + "mills");
        setTimeout(function() {
            console.log('reconnecting to MongoDB');
            lastReconnectAttempt=new Date().getTime();
            mongoose.connect(dbURI, {server:{auto_reconnect:true}});
        },delay);
    }
    else {
        console.log('reconnecting to MongoDB');
        lastReconnectAttempt=now;
        mongoose.connect(dbURI, {server:{auto_reconnect:true}});
    }

});

Ответ 7

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

(node: 18123) UnhandledPromiseRejectionWarning: отказ от необработанного обещания (идентификатор отказа: 1): MongoError: не удалось подключиться к серверу [localhost: 27017] при первом подключении

Версия ES6 (с обещанием)

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

import mongoose from 'mongoose';

mongoose.Promise = Promise; // Set mongoose to use ES6 Promises.

const dbURI = 'mongodb://127.0.0.1:27017/myDb';
const reconnectTimeout = 5000; // ms.

function connect() {
  mongoose.connect(dbURI, { auto_reconnect: true })
    .catch(() => {}); // Catch the warning, no further treatment is required
                      // because the Connection events are already doing this
                      // for us.
}

const db = mongoose.connection;

db.on('connecting', () => {
  console.info('Connecting to MongoDB...');
});

db.on('error', (error) => {
  console.error(`MongoDB connection error: ${error}`);
  mongoose.disconnect();
});

db.on('connected', () => {
  console.info('Connected to MongoDB!');
});

db.once('open', () => {
  console.info('MongoDB connection opened!');
});

db.on('reconnected', () => {
  console.info('MongoDB reconnected!');
});

db.on('disconnected', () => {
  console.error(`MongoDB disconnected! Reconnecting in ${reconnectTimeout / 1000}s...`);
  setTimeout(() => connect(), reconnectTimeout);
});

connect();

Дополнительная информация о событиях Connection.

Ответ 8

После прочтения документов я уверен, что у вас есть неправильные варианты. Строка параметров подключения должна выглядеть так:

mongoose.connect("mongodb://localhost:27017/db", {
    socketOptions: {
      // This option is on by default, but why not set it explicitly
      autoReconnect: true
    },
    // This options is 1 second by default, its possible the ha
    // takes longer than 30 seconds to recover.
    reconnectInterval: 5000,
    // This options is 30 by default, why not make it 60
    reconnectTries: 60
  })

Проверьте эту страницу: http://mongoosejs.com/docs/api.html

Ответ 9

Чтобы иметь несколько попыток без блокировки запроса во время повторной попытки, мне пришлось установить bufferMaxEntries: 0:

const dbUri = 'mongodb://localhost/some_db';
const dbOptions = {
    useMongoClient: true,
    autoReconnect: true,
    reconnectTries: Number.MAX_VALUE,
    bufferMaxEntries: 0
};

mongoose.connect(dbUri, dbOptions).catch(err => process.exit(1));

Ответ 10

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

const mongoose = require('mongoose')
const RETRY_TIMEOUT = 3000

module.exports = function initDB () {
  mongoose.Promise = global.Promise
  const options = {
    autoReconnect: true,
    useMongoClient: true,
    keepAlive: 30000,
    reconnectInterval: RETRY_TIMEOUT,
    reconnectTries: 10000
  }

  let isConnectedBefore = false

  const connect = function () {
    return mongoose.connect(process.env.MONGODB_URL, options)
      .catch(err => console.error('Mongoose connect(...) failed with err: ', err))
  }

  connect()

  mongoose.connection.on('error', function () {
    console.error('Could not connect to MongoDB')
  })

  mongoose.connection.on('disconnected', function () {
    console.error('Lost MongoDB connection...')
    if (!isConnectedBefore) {
      setTimeout(() => connect(), RETRY_TIMEOUT)
    }
  })
  mongoose.connection.on('connected', function () {
    isConnectedBefore = true
    console.info('Connection established to MongoDB')
  })

  mongoose.connection.on('reconnected', function () {
    console.info('Reconnected to MongoDB')
  })

  // Close the Mongoose connection, when receiving SIGINT
  process.on('SIGINT', function () {
    mongoose.connection.close(function () {
      console.warn('Force to close the MongoDB connection after SIGINT')
      process.exit(0)
    })
  })
}

Есть несколько отличий: я добавил некоторые опции, чтобы предотвратить проблему закрытия подключения - не пересоединяться после 30 автоматических попыток, просто MongoError: топология была уничтожена для любой операции и не восстанавливается; также я добавил .catch после подключения, чтобы предотвратить необработанное отклонение обещания):