【问题标题】:Mongoose Connection is not Restored when DB becomes accessible again当 DB 再次可访问时,Mongoose 连接未恢复
【发布时间】:2016-03-02 06:19:21
【问题描述】:

问题是 Mongoose 在以下情况下失去连接​​:

  1. Node App 已启动,一切正常(可访问数据库等)
  2. 本地运行的 Mongo 服务器进程(2.6.10 版)停止,然后在 15 秒后启动,一切正常(可访问数据库等)
  3. Mongo 进程已停止。
  4. 向 Express 发出请求,尝试访问 DB(使用 Mongoose) - 无法按预期访问。
  5. Mongo 进程已启动。
  6. 发出了相同的请求,即使 Mongo 已启动,也无法访问 DB。

如果我重新启动 Node JS 应用程序,一切正常。

为什么对 Mongo 的失败查询(使用 Mongoose 版本 4.4.5)会在 DB 进程再次启动时阻止连接恢复?

我们是否应该实施重试机制来尝试恢复连接,直到 DB 变得可访问?

我已经尝试过here提到的配置,但没有成功。

任何帮助将不胜感激。

下面是我们的连接助手的示例代码:

'use strict';

const _ = require('lodash');
const mongoose = require('mongoose');
const config = require('../config');
const logger = require('../logger');

const _instance = Symbol('instance');
const _enforcer = Symbol('enforcer');
const _members = Symbol('members');

/**
 * Singleton implementation of ConnectionHelper module
 * This module is responsible to reusing common db connections in the application

 * @type {ConnectionsHelper}
 */
module.exports = class ConnectionsHelper {
  constructor(enforcer) {
    if (enforcer !== _enforcer) {
      throw new Error('invalid singleton instantiation');
    }
    initConnectionFromConfig.call(this);
  }

  /**
   * The single instance
   * @returns {*}
     */
  static get instance() {
    if (!this[_instance]) {
      this[_instance] = new ConnectionsHelper(_enforcer);
    }
    return this[_instance];
  }

  /**
   * method retrieves connection by its name
   * @param connectionKey
   * @returns {*}
   */
  getConnection(connectionKey) {
    return this[_members][connectionKey];
  }

  /**
   * method disconnects all underlying connections
   * @returns {void|MongooseThenable}
   */
  closeConnections() {
    return mongoose.disconnect();
  }
};

function initConnectionFromConfig() {
  this[_members] = {};
  const dbsConnections = config.get('dbsConnections');

  _.forEach(dbsConnections, (connection, connectionName) => {

    const protocol = connection.protocol;
    const repSetPath = connection.mongoPath.join(',');
    const options = connection.options;

    options.server = {auto_reconnect: true, socketOptions: {keepAlive: 1, connectTimeoutMS: 30000 }};
    options.replset = {socketOptions: {keepAlive: 1, connectTimeoutMS: 30000 }};

    this[_members][connectionName] = mongoose.createConnection(protocol + repSetPath, options);

    addConnectionEvents.call(this, connectionName);
  });
}

function initConnectionIfNeeded() {
  this[_members] = {};
  const dbsConnections = config.get('dbsConnections');

  _.forEach(dbsConnections, (connection, connectionName) => {
    const protocol = connection.protocol;
    const repSetPath = connection.mongoPath.join(',');
    const options = connection.options;
    //options.server = {auto_reconnect: true, socketOptions: {keepAlive: 1, connectTimeoutMS: 30000 }};
    //options.replset = {socketOptions: {keepAlive: 1, connectTimeoutMS: 30000 }};

    this[_members][connectionName] = mongoose.createConnection(protocol + repSetPath, options);
    addConnectionEvents.call(this, connectionName);
  });
}

function addConnectionEvents(connectionName) {
  const connection = this[_members][connectionName];

  connection.on('connected', () => {
    logger.debug(`Mongoose connection open`);
  });
  connection.on('error', (err) => {
    logger.debug(`Mongoose connection error: ${err}`);
  });
  connection.on('exception', (err) => {
    logger.debug(`Mongoose connection exception: ${err}`);
  });
  connection.on('disconnected', () => {
    logger.debug(`Mongoose connection disconnected`);
  });
  connection.on('reconnected', () => {
    logger.debug(`Mongoose connection reconnected`);
  });
  connection.on('open', () => {
    logger.debug(`Mongoose connection is open`);
  });
  // If the Node process ends, close the Mongoose connection
  process.on('SIGINT', () => {
    connection.close(() => {
      logger.debug(`Mongoose default connection disconnected through app termination`);
      process.exit(0);
    });
  });
}

【问题讨论】:

  • 您能告诉我们您的 mongodb 连接代码吗?
  • options.server = {auto_reconnect: true, socketOptions: {keepAlive: 1, connectTimeoutMS: 30000 }}; options.replset = {socketOptions: {keepAlive: 1, connectTimeoutMS: 30000 }}; this[_members][connectionName] = mongoose.createConnection(protocol + repSetPath, options);
  • 你能给我们更多的代码吗? this 在哪里使用?在一个模块中?你是从这个模块导出的吗?顺便说一句,您可以直接将代码添加到您的问题中......

标签: node.js mongodb express mongoose


【解决方案1】:

我遇到了同样的问题。我所做的是在这里重新启动猫鼬:

connection.on('disconnected', () => {
    logger.debug(`Mongoose connection disconnected`);
    mongoose.connect(path);
  });

而且我还使用 setTimeout() 使其每 3 秒尝试一次。

mongoose.connection.on('disconnected', function () {  
  console.log('Mongoose default connection disconnected'); 
  console.log("Trying to reconnect");

  function connect(){
    mongoose.connect(dbPath, function(err){
      if(err) console.log("Error while trying to reconnect to MongoDB");
    });
  }
  setTimeout(connect, 3000);
});

我也使用 ForeverJS。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-22
    相关资源
    最近更新 更多