Mongoose: コヌルバックは起こりたせん

䜜成日 2016幎09月13日  Â·  53コメント  Â·  ゜ヌス: Automattic/mongoose

私は数幎前からmongooseを䜿甚しおいたすが、最近、接続が倱われおいるように芋えるずいう問題がたくさんありたす。

接続蚭定

// Connecting to MongoDB 3.2.1
var connString = "mongodb://xxxxx:xxxxx<strong i="8">@xxxxx</strong>:xxxx,xxxx:xxxx/xxx?ssl=true";
var connOptions = {
  "mongos": { "ssl": true, "sslValidate": false }
};
mongoose.connect(connString, connOptions, function(err, db) {
  if(err) { console.log("Error connecting to db: "+err); }
});

問題

マングヌスはただ電話をかけ盎すのをやめたす。 ゚ラヌは発生せず、メモリ/ CPUはサヌバヌずデヌタベヌスで問題なく、他のサヌバヌから接続できたす。 再起動するず垞に修正されたす。

db.Something.count({}, callback);

バヌゞョン

mongoose 4.4.11 、コヌルバックが停止したずきのmongoose.connection.readyState === UNAUTHORIZED 。

そこで、 mongoose 4.6.0にアップグレヌドしたしたが、4時間以内にコヌルバックが再び停止し、 mongoose.connection.readyState === CONNECTED 。

䜕か案は

これを起こさないようにする方法はありたすか

これ以䞊デバッグ情報を収集できおうれしいです。取埗する情報を教えおください。

underlying library issue

最も参考になるコメント

残念ながら、mongodbドラむバヌのリリヌスが保留されおいるため、これをもう䞀床プッシュする必芁がありたす。 申し蚳ありたせんが、今しばらくお埅ちいただきたすようお願いいたしたす+1🌎

党おのコメント53件

スタンドアロン、レプリカセット、たたはシャヌドクラスタヌに接続しおいたすか たた、SSLを䜿甚しおいるこずを確認できたすか

これは私にずっお過去数日間の倧きな問題でした。 実行䞭のすべおのアプリケヌションは、むベントルヌプがどんどん遅くなり、システム党䜓の遅延が増加したした。 Nodeアプリケヌションを再起動するず、毎回問題が解決し、数分たたは数時間の操䜜埌に問題が再発したした。

マングヌス4.5.10に戻すず、問題が解決したした。

  • レプリカセットに接続しおいたす
  • SSLの䜿甚

4.6.0の同様の問題で、レプリカセットに接続しおいるかどうかはわかりたせんが、SSLを䜿甚しおいるこずは間違いありたせん。

FWIW、4.6.0は垞に接続を切断しおいたした。 4.5.10は良いです。

@djanowski接続コヌドがどのように芋えるか、どのバヌゞョンのmongodbを䜿甚しおいるかなど、さらに情報を提䟛できたすか

@ vkarpov15 MongoDB3.2.6を䜿甚しおいたした。

接続オプション

auth: {
  authMechanism: 'SCRAM-SHA-1',
},
mongos: {
  ssl: true,
  sslValidate: true,
  sslCA: [cert],
},

単䞀のモンゎたたは耇数のモンゎ

耇数のモンゎ。 ComposeMongoデプロむメントを䜿甚したす。

これのトラブルシュヌティングを支揎するために他にできるこずはありたすか これにより、新しいバヌゞョンぞの移行が劚げられおいたす...

あなたのコヌドを芋ずに本圓の仮説を立おるのは難しいです。 mongoose.connectに接続しおいる堎合は、この問題が発生し始めたずきにmongoose.connection.readyStateの倀を確認したす。 たた、マングヌスのデバッグモヌドmongoose.set('debug', true)有効にしたす。これにより、マングヌスの操䜜ごずにデバッグメッセヌゞがコン゜ヌルに出力されたす。 それらのメッセヌゞが印刷されおいるかどうかは、間違いなくデバッグに圹立ちたす。

@ vkarpov15これは私が接続するために䜿甚しおいるコヌドです https  //gist.github.com/sommestad/c0c6a7fa4feaadf84ecbb59cc3432c90
これはプラむベヌトモゞュヌルの䞀郚であるため、芁点です。

_接続ラッピングモゞュヌルの理由は、接続が他のプラむベヌトNPMモゞュヌルで再利甚されるこずがあるためです。これは、これたでマングヌスではうたく機胜しおいたせんでした。_

これらの問題が発生したずきに接続状態のログを有効にしたしたが、接続自䜓は倉曎されおいないようです少なくずもむベントは発行されたせんでした。 そのため、クラむアントが切断されたようには芋えたせんでした。

URIのreplicaSetず接続しおいたせんタヌゲットデヌタベヌスはCompose Deploymentです。 前述のように、SSLが䜿甚されたす。 たた、トラフィックはAWSNATゲヌトりェむを介しおルヌティングされたす。 AWS NATのアむドルタむムアりトは5分ですが、これらの問題はトラフィックが倚い堎合でも発生したした。

私にずっおいく぀かの問題、あなたはそれを解決したしたか

@ youth7いやアむデアはありたせん。 たた、composeデプロむメントに接続しおいたすか 远加情報を提䟛しおください

これの原因を芋぀けるために私ができるこずは他にありたすか 調査できる理論はありたすか

@sommestad具䜓的なこずは䜕もありたせん。 䜜曲からのログはありたすか

mongoose 4.7.2を詊したしたが、48時間埌に同じ問題が発生したした。 この時点で、私は独自の問題を抱えおいる4.4.11悩たされおいたす。

ログを収集するこずを期埅しおデモサヌバヌに4.7.2をむンストヌルしたしたが、問題なく2週間実行されおいたす。 たぶん、デヌタ/接続などの量が問題を匕き起こしたすか

それが起こり始めるず、それを再珟するためのコヌドは非垞に簡単です。 基本的に、ク゚リのコヌルバックはすべお消えたす。

db.Something.find({}, callback); //this callback is never fired

私が蚀ったように、これが起こっおいるずき、 mongoose.connection.readyState === CONNECTED

倉。 私はmongodbログを意味したした-その゚ラヌが発生したずきからmongodbサヌバヌログをダンプできたすか

この障害が発生したずきにDBログをスキャンしたずころ、異垞なこずは䜕も芋られたせんでした。 接続数、切断数、接続の問題などに関連する問題はありたせんでした。 たた、順䞍同で䜕も芋えなかったComposeにも連絡を取りたした。

@bendytree HTTP負荷テストツヌルを䜿甚しお、そのデモサヌバヌにボリュヌムをスロヌできたすか

@bendytreeたた、ノヌドのすべおのリリヌスラむン4.x、6.x、7.xで発生したすか

@ vkarpov15最新のMongoDBドラむバヌでテストできるように、4.7.7を

@ vkarpov15 66d559b19a86c70e30a8f083d03eb22566571b7eありがずう やっおみたす。

ここでも同じですが、ここではSSLレプリカで、数分/時間埌、リク゚ストはcallbackで停止しさらに詳现なログを远加したした、゚ラヌは発生したせん。 昚倜4.7.7にアップグレヌドしたしたが、ただ問題がありたす。

線集4.7.0にダりングレヌドしようずしたしたが、最悪でした5分以内に問題が発生したした。 4.5.10を詊しおいたす。

@gierschvノヌド6.9.x

@djanowskiいいえ、ただ4.6 / 4.7.xLTSです。

@djanowskiノヌド4.4.2でのみ詊したした

この問題の重耇の可胜性のあるリストを保持する

  • 4638
  • 4690
  • 4901

参考たでに、4.5.10はここではうたく機胜しおいるようで、過去5時間は問題ありたせん。 たた、すべおのマシンで4690のような高いCPU䜿甚率がありたしたが、これもダりングレヌドによっお修正されたようです。

ここに新しい開発はありたせんか バグを芋぀けるために私たちにできるこずは他にありたすか

@sommestad最新のマングヌスでただこの問題がありたすか

前回は基本的にシステム党䜓が壊れたので、ただあえおアップグレヌドしおいたせん倉曎は「しばらくしお」から衚瀺されるため、長時間実行しないず確認が困難です。 修正されたず信じる理由がある堎合は、システムのより分離された郚分を詊すこずができたすか

線集ping @varunjayaraman

私の偎では、ノヌド6.x LTSに切り替えお、数週間前に最埌のマングヌスバヌゞョンにアップグレヌドしたしたが、それ以降は問題ありたせん。

箄2か月前にノヌド6.10.2、マングヌス4.9.9にアップグレヌドしたした。 ただ同じ問題が発生しおいたす。

接続文字列の圢匏はmongodb://username:[email protected]:1234,db2.com:2345/db-name?ssl=trueです。

console.log("fetching user...");
userCollection.findOne({_id: userId}, function(err, user){
  console.log("done"); // this never happens
  ...
});

コヌルバックが停止するず、再び開始するこずはありたせん。 プロセスを再開するず、正垞に接続されたす。

トラブルシュヌティングに圹立぀デヌタを収集できる堎合は、ぜひサポヌトさせおいただきたす。

同じ問題が発生しおおり、以䞋のコヌドで再珟できたす高速なモックアップ/コヌドスタむルで申し蚳ありたせん。

接続タむムアりトをシミュレヌトするために、poolSizeを1に䞋げ、次の順序で呌び出される2぀の゚ンドポむント通垞/䜎速ぞの芁求をトリガヌしたす。

  1. 通垞の゚ンドポむント結果をすぐに返したす
  2. 遅い゚ンドポむント遅いク゚リを開始したす
  3. 通垞の゚ンドポむント2で䜿甚されおいるため、䜿甚可胜な接続を埅機したす
  4. 通垞の゚ンドポむント2ず3でMongoError /接続タむムアりトが発生した堎合、1分埌にトリガヌされたす

以䞋を䜿甚しお耇補したす。

// Require modules
const mongoose = require('mongoose');
const express = require('express');
const request = require('request');
const parseJson = require('body-parser').json();

// Use native Promises in Mongoose
mongoose.Promise = Promise;

// Create the test schema
const testSchema = new mongoose.Schema({
  name: {
    type: String,
    trim: true,
    default: 'test'
  }
});

// Create the mongoose model
mongoose.model('Test', testSchema, 'test');

// Create some test data
mongoose.model('Test').create([
  {name: 'test1'},
  {name: 'test2'},
  {name: 'test3'},
  {name: 'test4'},
  {name: 'test5'}
]);

// Create the Express based app
const app = express();

// Create the express router
const router = express.Router();

// Create a normal route
router.route('/normal').get(parseJson, function (req, res, next) {
  mongoose.model('Test').find({}).then(
    function (data) {
      res.status(200).json(data);
    }
  ).catch(
    function (err) {
      res.status(400).json(err);
    }
  );
});

// Create up a slow route
router.route('/slow').get(parseJson, function (req, res, next) {
  mongoose.model('Test').find({$where: 'sleep(10000) || true'}).then(
    function (data) {
      res.status(200).json(data);
    }
  ).catch(
    function (err) {
      res.status(400).json(err);
    }
  );
});

// Add middleware to console log every request
var requestNumber = 1;
app.use(function (req, res, next) {
  console.log('Request ' + requestNumber, req.method, req.url);
  requestNumber++;
  next();
});

// Use the router
app.use('/', router);

// Listen for requests
app.listen(4000, function () {
  console.log('Server listening on port 4000');
});

// Catch any uncaught exceptions
process.on('uncaughtException', function (err) {
  console.log('Uncaught exception', err);
});

// Catch any unhandled rejections
process.on('unhandledRejection', function (reason) {
  console.error('Unhandled Rejection', reason);
});

// Database connection options
const connectionOpts = {
  // Use the new connection logic
  useMongoClient: true,

  // Do not auto reconnect (the Node code will auto reconnect)
  autoReconnect: false,

  // Use a poolsize of 1 to simulate a timeout using multiple request to slow and normal endpoints
  poolSize: 1
};

// Connection method with retry
const connectWithRetry = function () {
  // Check if we still need to connect
  if (mongoose.connection.readyState !== mongoose.Connection.STATES.connected) {
    // Connect
    return mongoose.connect('mongodb://localhost:27017/test', connectionOpts).catch(
      function (err) {
        console.log('Can not connect to mongo', err);
      }
    );
  }
};

// Helper function to execute a request to the normal endpoint
const doRequestNormal = function () {
  request({
    url: 'http://localhost:4000/normal',
    json: true,
    timeout: 60000
  }, function (error, response, body) {
    if (error) {
      console.log('Error on normal request', error, response);
    }
    console.log('Performed normal request, body:', body);
  });
};

// Helper function to execute a request to the normal endpoint
const doRequestSlow = function () {
  request({
    url: 'http://localhost:4000/slow',
    json: true,
    timeout: 60000
  }, function (error, response, body) {
    if (error) {
      console.log('Error on slow request', error, response);
    }
    console.log('Performed slow request', body);
  });
};

// Helper function to simulate requests
const doRequests = function () {
  doRequestNormal();
  doRequestSlow();
  doRequestNormal();

  setTimeout(function () {
    console.log('Do normal request after 1 minute');
    doRequestNormal();
  }, 60000);
};

// Connecting event
mongoose.connection.on('connecting', function () {
  console.log('Connecting to database...');
});

// Connected event
mongoose.connection.on('connected', function () {
  console.log('Database is connected, start requesting...');
  doRequests();
});

// Timeout event
mongoose.connection.on('timeout', function (err) {
  console.log('Database timeout error', err);
});

// Error event
mongoose.connection.on('error', function (err) {
  console.log('Database connection error', err);
});

// Disconnected event
mongoose.connection.on('disconnected', function () {
  console.error('Database got disconnected, reconnecting in 5 sec...');

  // Reconnect in 5 seconds
  setTimeout(connectWithRetry, 5000);
});

// Connect to the database with retry
connectWithRetry();

// Log the connection state every 10 seconds
setInterval(function () {
  console.log('Mongoose connection readystate is', mongoose.connection.readyState);
}, 10000);

コン゜ヌル出力は次のずおりです。

Connecting to database...
Server listening on port 4000
Database is connected, start requesting...
Request 1 GET /normal
Request 2 GET /slow
Request 3 GET /normal
Performed normal request, body: [ { _id: '597f8c6f41bf2e119594ba1a', __v: 0, name: 'test1' },
  { _id: '597f8c6f41bf2e119594ba1b', __v: 0, name: 'test2' },
  { _id: '597f8c6f41bf2e119594ba1c', __v: 0, name: 'test3' },
  { _id: '597f8c6f41bf2e119594ba1d', __v: 0, name: 'test4' },
  { _id: '597f8c6f41bf2e119594ba1e', __v: 0, name: 'test5' } ]
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Performed slow request { name: 'MongoError',
  message: 'connection 0 to localhost:27017 timed out' }
Performed normal request, body: { name: 'MongoError',
  message: 'connection 0 to localhost:27017 timed out' }
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Do normal request after 1 minute
Request 4 GET /normal
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Error on normal request { Error: ESOCKETTIMEDOUT
    at ClientRequest.<anonymous> (/Users/adriaanmeuris/Documents/Projecten/Mongoose timeout/node_modules/request/request.js:819:19)
    at ClientRequest.g (events.js:291:16)
    at emitNone (events.js:86:13)
    at ClientRequest.emit (events.js:185:7)
    at Socket.emitTimeout (_http_client.js:620:10)
    at Socket.g (events.js:291:16)
    at emitNone (events.js:86:13)
    at Socket.emit (events.js:185:7)
    at Socket._onTimeout (net.js:339:8)
    at ontimeout (timers.js:365:14)
    at tryOnTimeout (timers.js:237:5)
    at Timer.listOnTimeout (timers.js:207:5) code: 'ESOCKETTIMEDOUT', connect: false } undefined
Performed normal request, body: undefined
Mongoose connection readystate is 1
Mongoose connection readystate is 1

デヌタベヌスのreadyStateを10秒ごずに監芖しおいたす。これは、接続がただアクティブであるこずを瀺しおいたす。 Mongoose゚ラヌ/タむムアりトむベントはトリガヌされず、リク゚スト4のコヌルバックは呌び出されたせんリク゚ストパッケヌゞを䜿甚しお60秒埌にタむムアりトしたす。 http// localhost 4000 / slowおよび次のhttp// localhost 4000 / normalにアクセスしおテストするこずもできたす。

https://team.goodeggs.com/reconnecting-to-mongodb-when-mongoose-connect-fails-at-startup-83ca8496ca02に基づく自動再接続ロゞックを䜿甚しおいたすが、mongoが切断されないため、これがトリガヌされるこずはありたせん。

ある堎合には、テストデヌタを䜜成するコヌドにコメントするず再珟できないこずがありたすしたがっお、基本的に空のコレクションをク゚リしたす

考えられる関連する問題

  • 4789
  • 4660

どんな助けでも倧歓迎です。

そこで、mongooseを䜿甚せずにnode-mongodb-nativeを操䜜するために、䞊蚘のスクリプトを曞き盎しおさらに掘り䞋げたした。 結果は今では倧きく異なりたす。

接続蚭定ず芁求は同じです。

  1. 通垞の゚ンドポむント結果をすぐに返したす
  2. 遅い゚ンドポむント遅いク゚リを開始したす
  3. 通垞の゚ンドポむント2で䜿甚されおいるため、䜿甚可胜な接続を埅機したす
  4. 通垞の゚ンドポむント1分埌にトリガヌされたす

コヌド

// Require modules
const MongoClient = require('mongodb').MongoClient;
const Server = require('mongodb').Server;
const express = require('express');
const request = require('request');
const parseJson = require('body-parser').json();

// The db reference
var db;

// Function to insert test data
function insertTestData() {
  return new Promise(function (resolve, reject) {
    // Get the test collection
    var test = db.collection('test');

    // Insert some documents
    test.insertMany([
      {name: 'test1'},
      {name: 'test2'},
      {name: 'test3'},
      {name: 'test4'},
      {name: 'test5'}
    ], function (err, result) {
      if (err) {
        reject(err);
      } else {
        resolve();
      }
    });
  });
}

// Create the Express based app
const app = express();

// Create the express router
const router = express.Router();

// Create a normal route
router.route('/normal').get(parseJson, function (req, res, next) {
  // Get the documents collection
  var collection = db.collection('test');

  // Find some documents
  collection.find({}).toArray(function (err, data) {
    if (err) {
      res.status(400).json(err);
    } else {
      res.status(200).json(data);
    }
  });
});

// Create up a slow route
router.route('/slow').get(parseJson, function (req, res, next) {
  // Get the documents collection
  var collection = db.collection('test');

  // Find some documents
  collection.find({$where: 'sleep(10000) || true'}).toArray(function (err, data) {
    if (err) {
      res.status(400).json(err);
    } else {
      res.status(200).json(data);
    }
  });
});

// Add middleware to console log every request
var requestNumber = 1;
app.use(function (req, res, next) {
  console.log('Request ' + requestNumber, req.method, req.url);
  requestNumber++;
  next();
});

// Use the router
app.use('/', router);

// Listen for requests
app.listen(4000, function () {
  console.log('Server listening on port 4000');
});

// Catch any uncaught exceptions
process.on('uncaughtException', function (err) {
  console.log('Uncaught exception', err);
});

// Catch any unhandled rejections
process.on('unhandledRejection', function (reason) {
  console.error('Unhandled Rejection', reason);
});

// Database connection options
const connectionOpts = {
  // Do not auto reconnect (the Node code will auto reconnect)
  autoReconnect: false,

  // Use a poolsize of 1 to simulate a timeout using multiple request to slow and normal endpoints
  poolSize: 1
};

// Connection method with retry
const connectWithRetry = function () {

  return MongoClient.connect('mongodb://localhost:27017/test', connectionOpts).then(
    function (database) {
      db = database;
      setupEvents();
      console.log('Connected to mongo');
    }
  ).catch(
    function (err) {
      console.log('Can not connect to mongo', err);
      return err;
    }
  );
};

// Helper function to execute a request to the normal endpoint
const doRequestNormal = function () {
  request({
    url: 'http://localhost:4000/normal',
    json: true,
    timeout: 60000
  }, function (error, response, body) {
    if (error) {
      console.log('Error on normal request', error, response);
    }
    console.log('Performed normal request, body:', body);
  });
};

// Helper function to execute a request to the normal endpoint
const doRequestSlow = function () {
  request({
    url: 'http://localhost:4000/slow',
    json: true,
    timeout: 60000
  }, function (error, response, body) {
    if (error) {
      console.log('Error on slow request', error, response);
    }
    console.log('Performed slow request', body);
  });
};

// Helper function to simulate requests
const doRequests = function () {
  doRequestNormal();
  doRequestSlow();
  doRequestNormal();

  setTimeout(function () {
    console.log('Do normal request after 1 minute');
    doRequestNormal();
  }, 60000);
};

// Helper function to setup mongo events
function setupEvents() {
// Connecting event
  db.on('connecting', function () {
    console.log('Connecting to database...');
  });

// Connected event
  db.on('connected', function () {
    console.log('Database is connected, start requesting...');
  });

// Timeout event
  db.on('timeout', function (err) {
    console.log('Database timeout error', err);
  });

// Error event
  db.on('error', function (err) {
    console.log('Database connection error', err);
  });

// Disconnected event
  db.on('close', function () {
    console.error('Database got disconnected, reconnecting in 5 sec...');

    // Reconnect in 5 seconds
    setTimeout(connectWithRetry, 5000);
  });
}

// Connect to the database with retry
connectWithRetry().then(
  function () {
    return insertTestData();
  }
).then(
  function () {
    doRequests();
  }
);

コン゜ヌル出力は次のずおりです。

Server listening on port 4000
Connected to mongo
Request 1 GET /normal
Request 2 GET /slow
Request 3 GET /normal
Performed normal request, body: [ { _id: '598207c16caf9224cf3b8897', name: 'test1' },
  { _id: '598207c16caf9224cf3b8898', name: 'test2' },
  { _id: '598207c16caf9224cf3b8899', name: 'test3' },
  { _id: '598207c16caf9224cf3b889a', name: 'test4' },
  { _id: '598207c16caf9224cf3b889b', name: 'test5' } ]
Performed slow request [ { _id: '598207c16caf9224cf3b8897', name: 'test1' },
  { _id: '598207c16caf9224cf3b8898', name: 'test2' },
  { _id: '598207c16caf9224cf3b8899', name: 'test3' },
  { _id: '598207c16caf9224cf3b889a', name: 'test4' },
  { _id: '598207c16caf9224cf3b889b', name: 'test5' } ]
Performed normal request, body: [ { _id: '598207c16caf9224cf3b8897', name: 'test1' },
  { _id: '598207c16caf9224cf3b8898', name: 'test2' },
  { _id: '598207c16caf9224cf3b8899', name: 'test3' },
  { _id: '598207c16caf9224cf3b889a', name: 'test4' },
  { _id: '598207c16caf9224cf3b889b', name: 'test5' } ]
Do normal request after 1 minute
Request 4 GET /normal
Performed normal request, body: [ { _id: '598207c16caf9224cf3b8897', name: 'test1' },
  { _id: '598207c16caf9224cf3b8898', name: 'test2' },
  { _id: '598207c16caf9224cf3b8899', name: 'test3' },
  { _id: '598207c16caf9224cf3b889a', name: 'test4' },
  { _id: '598207c16caf9224cf3b889b', name: 'test5' } ]

前のスクリプトのようにMongo゚ラヌ/タむムアりトむベントはトリガヌされたせんが、リク゚スト2ず3は正しく解決され、リク゚スト4のコヌルバックもトリガヌされたす-Mongooseを䜿甚しおいるスクリプトずは察照的です。

私はこれがマングヌスずモンゎの問題であるかどうかを陀倖しようずしおいたす-したがっお、これらのスクリプトの結果を比范するこずに関する助けをいただければ幞いです。 たぶん@ vkarpov15はこれにチャむムを

@adriaanmeurisは奇劙です。これが、最初のスクリプトの実行から埗られる出力です。

$ node gh-4513.js 
Connecting to database...
Server listening on port 4000
Database is connected, start requesting...
Request 1 GET /normal
Request 2 GET /slow
Request 3 GET /normal
Performed normal request, body: [ { _id: '5998e4a79bb81d37ac4b1a26', __v: 0, name: 'test1' },
  { _id: '5998e4a79bb81d37ac4b1a27', __v: 0, name: 'test2' },
  { _id: '5998e4a79bb81d37ac4b1a28', __v: 0, name: 'test3' },
  { _id: '5998e4a79bb81d37ac4b1a29', __v: 0, name: 'test4' },
  { _id: '5998e4a79bb81d37ac4b1a2a', __v: 0, name: 'test5' } ]
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Performed slow request [ { _id: '5998e4a79bb81d37ac4b1a26', __v: 0, name: 'test1' },
  { _id: '5998e4a79bb81d37ac4b1a27', __v: 0, name: 'test2' },
  { _id: '5998e4a79bb81d37ac4b1a28', __v: 0, name: 'test3' },
  { _id: '5998e4a79bb81d37ac4b1a29', __v: 0, name: 'test4' },
  { _id: '5998e4a79bb81d37ac4b1a2a', __v: 0, name: 'test5' } ]
Performed normal request, body: [ { _id: '5998e4a79bb81d37ac4b1a26', __v: 0, name: 'test1' },
  { _id: '5998e4a79bb81d37ac4b1a27', __v: 0, name: 'test2' },
  { _id: '5998e4a79bb81d37ac4b1a28', __v: 0, name: 'test3' },
  { _id: '5998e4a79bb81d37ac4b1a29', __v: 0, name: 'test4' },
  { _id: '5998e4a79bb81d37ac4b1a2a', __v: 0, name: 'test5' } ]
Mongoose connection readystate is 1
Do normal request after 1 minute
Request 4 GET /normal
Performed normal request, body: [ { _id: '5998e4a79bb81d37ac4b1a26', __v: 0, name: 'test1' },
  { _id: '5998e4a79bb81d37ac4b1a27', __v: 0, name: 'test2' },
  { _id: '5998e4a79bb81d37ac4b1a28', __v: 0, name: 'test3' },
  { _id: '5998e4a79bb81d37ac4b1a29', __v: 0, name: 'test4' },
  { _id: '5998e4a79bb81d37ac4b1a2a', __v: 0, name: 'test5' } ]
Mongoose connection readystate is 1
Mongoose connection readystate is 1
^C
$ 

マングヌスは接続を維持したす。 mongodb、node、mongooseのバヌゞョンを明確にできたすか

テストしおくれおありがずう 実際、Mongooseは垞に接続されたたたですが、コヌルバックは発生しなくなりたすExpressにリク゚ストが届くのを確認できたすが、タむムアりトしたす

私はテストしおいたした

  • ノヌド6.8.1
  • mongodb 2.2.30
  • マングヌス4.11.5

曎新したした

  • ノヌド6.8.1
  • mongodb 2.2.31
  • マングヌス4.11.7

最初に投皿したスクリプトを䜿甚しお、問題をロヌカルで再珟できたす。 これは、Mongo接続がタむムアりトしたずきにのみ発生するため、これをシミュレヌトするク゚リを倉曎するこずをお勧めしたす。

mongoose.model('Test').find({$where: 'sleep(10000) || true'})

これによりすべおのマシンでタむムアりトがトリガヌされるかどうかはわかりたせん。そのため、再珟するにはこのク゚リを倉曎する必芁がある堎合がありたす

マングヌス4.10.4にアップデヌトした埌、これらの問題は発生しなくなりたした。
他の人が問題を経隓しおいるように芋えるので、少し奇劙に思えたすが、問題が再発する兆候がなく、数週間にわたっお倚くのサヌビスが実行されおいたす。 🀔

ただし、以前は@adriaanmeurisず同じ方法で問題が発生したため、タむムアりトが発生しおいない可胜性がありたす。

ノヌド8を実行しおいたす。

この問題はただ定期的に発生しおいたす。

@adriaanmeurisのスクリプトでは再珟できたせんでしたが、毎回再珟する修正バヌゞョンを次に瀺したす。

ベンディツリヌ/マングヌス-問題-4513

@bendytreeに感謝したす、あなたのスクリプトで私も再珟できたす

7) Database connecting...
49) Database connected...
49) Dropping...
57) Creating...
156) FastQuery-A: starting...
166) FastQuery-A: success: 1
1158) SlowQuery: starting...
2158) FastQuery-B: starting...
362165) SlowQuery: failed: MongoError: connection 0 to localhost:27017 timed out
362167) FastQuery-B: failed: MongoError: connection 0 to localhost:27017 timed out
605159) FastQuery-C: starting...
1210149) Giving Up...

これは基本的に私のスクリプトず同じですが、タむムアりト時間が長くなりたす。 誰もが私のスクリプト10秒のスリヌプを䜿甚で再珟できるわけではないため、ロヌカルでタむムアりトをシミュレヌトするのにかかる時間は、セットアップに応じお増枛するず思いたす。

@ vkarpov15この曎新されたスクリプトを詊すこずができたすか マングヌス4.8.11でテストしお再珟したした。

@bendytreeでなんずかsocketTimeoutMSが䜎すぎる堎合です。 NS

362591) SlowQuery: failed: MongoError: connection 0 to localhost:27017 timed out
362591) FastQuery-B: failed: MongoError: connection 0 to localhost:27017 timed out

メッセヌゞは、mongodbドラむバヌの゜ケットがタむムアりトしたこずを瀺しおいたす。 mongodbドラむバヌはデフォルトで30秒埌にタむムアりトしたすが、OSにも泚意が必芁な゜ケットタむムアりトがあるため、15秒以䞊かかるク゚リは避けるこずをお勧めしたす。 ただし、 socketTimeoutMSオプションを䜿甚しお、mongodbの゜ケットタむムアりトを構成できたす。

mongoose.connect(DB_URL, {
  useMongoClient: true,
  autoReconnect: false,
  poolSize: 1,
  socketTimeoutMS: 0
}).catch((err)=>{ log('Connect failed', err); });

そのオプションを0に蚭定するず、スクリプトは私のマシンでほが成功し、10分間のク゚リはただ終了したすが、コヌルバックは続行されたす

$ node gh-4513.js 
9) Database connecting...
43) Database connected...
43) Dropping...
53) Creating...
177) FastQuery-A: starting...
189) FastQuery-A: success: 1
1174) SlowQuery: starting...
2174) FastQuery-B: starting...
601181) SlowQuery: failed: MongoError: Interrupted by the host
601182) FastQuery-B: success: 1
605173) FastQuery-C: starting...
605174) FastQuery-C: success: 1

しかし、埌続のク゚リは成功したす。

いずれにせよ、この堎合、マングヌスはタむムアりトむベントを発行するはずなので、その問題を修正したす。

connectTimeoutMSデフォルトは30000msずsocketTimeoutMSデフォルトは360000msを混同しおいるず思いたす。

socketTimeoutMSを、ドラむバヌを介しお実行される最も遅い操䜜の長さの2〜3倍に蚭定するこずをお勧めしたす。socketTimeoutMSを0に蚭定するず、実際にはオペレヌティングシステムのデフォルトの゜ケットタむムアりト倀が適甚されたす詳现に぀いおは、http//mongodb.github.io/を参照しおください。 node-mongodb-native / 2.2 / reference / faq /。

したがっお、この質問は残りたす。この制限固定たたはデフォルトのOSタむムアりトに達したずきに、なぜこれらのコヌルバックが発生しなくなるのですか

vkarpov15 @ [email protected] 、私は今、そのためのおかげでタむムアりトむベントを参照しおください。 ただし、このコヌルバックの問題は匕き続き発生したす @bendytreeの元のスクリプトを䜿甚するず、テストを高速化するために、LONG_QUERY_DURATION_IN_MSを2000に、socketTimeoutMSを1000に蚭定できたす

私はさらにいく぀かのテストを行い、これがマングヌスなしでも再珟できるこずを発芋したした。 http://mongodb.github.io/node-mongodb-native/2.2/reference/faq/を読んでいるず、 Closing the socket forces a reconnect of the driver’s connection pool and introduces latency to any other operations which are queued upであるこずがわかりたした。

mongoose.connection.readyStateは垞に1ですが、 autoReconnectをtrueに蚭定しおみたしたが、スクリプトを再実行したした。

8) Database connecting...
47) Database connected...
48) Dropping...
73) Creating...
123) FastQuery-A: starting...
129) FastQuery-A: success: 1
1122) SlowQuery: starting...
2126) FastQuery-B: starting...
3130) Database timeout...
3133) SlowQuery: failed: MongoError: connection 0 to localhost:27017 timed out
3133) FastQuery-B: failed: MongoError: connection 0 to localhost:27017 timed out
6063) Database timeout...
7122) FastQuery-C: starting...
7125) FastQuery-C: success: 1
8129) Database timeout...
11070) Database timeout...
13073) Database timeout...

したがっお、コヌルバックはautoReconnectをtrueに蚭定しお機胜しおいるようです👍

この蚘事をさらに読んだずき http 

だから私はautoReconnectをfalse autoReconnect戻しおみたした+ bufferMaxEntriesを0 、これは出力です

8) Database connecting...
51) Database connected...
51) Dropping...
58) Creating...
112) FastQuery-A: starting...
116) FastQuery-A: success: 1
1115) SlowQuery: starting...
2115) FastQuery-B: starting...
3123) Database timeout...
3123) SlowQuery: failed: MongoError: connection 0 to localhost:27017 timed out
3123) FastQuery-B: failed: MongoError: connection 0 to localhost:27017 timed out
7115) FastQuery-C: starting...
7117) FastQuery-C: failed: MongoError: no connection available for operation and number of stored operation > 0

これは、 @ bendytreeのスクリプトの最初のバヌゞョンでコヌルバックがトリガヌされなかった理由を説明しおいたす。

@ vkarpov15これで、2぀の質問が

  • 接続むベントが発行されないのはなぜですか切断されたむベントが衚瀺されるず思いたす
  • タむムアりトむベントむベントが発生し続けるようです

曎新されたスクリプトは次のずおりです

const LONG_QUERY_DURATION_IN_MS = 2000;
const DB_URL = 'mongodb://localhost:27017/test_mongoose_callbacks';

const mongoose = require('mongoose');
mongoose.Promise = Promise;

var startTime = new Date().getTime();
var log = (msg) => {
  var seconds = Math.round(new Date().getTime() - startTime);
  console.log(seconds+") "+msg);
};

var Model = mongoose.model('Test', new mongoose.Schema({
  name: { type: String, trim: true, default: 'test' }
}), 'test');

mongoose.connection.on('connecting',   () => { log('Database connecting...'); });
mongoose.connection.on('timeout',      () => { log('Database timeout...'); });
mongoose.connection.on('error',        () => { log('Database error...'); });
mongoose.connection.on('disconnected', () => { log('Database disconnected...'); });

const doRequest = function (title, slow) {
  var logRequest = (msg) => { log(title+": "+msg); };

  logRequest("starting...");
  var filter = slow ? {$where: 'sleep('+LONG_QUERY_DURATION_IN_MS+') || true'} : {};
  Model.count(filter).exec((err, count) => {
    logRequest(err ? "failed: "+err : "success: "+count);
  });
};

mongoose.connection.on('connected', () => {
  log("Database connected...");
 log("Dropping...");
 mongoose.connection.db.dropDatabase(function(){
   log("Creating...");
   Model.create([ {name: 'test1'} ], function(){
      setTimeout(() => { doRequest("FastQuery-A", false); }, 0);
      setTimeout(() => { doRequest("SlowQuery", true);  }, 1000);
      setTimeout(() => { doRequest("FastQuery-B", false); }, 2000);
      setTimeout(() => { doRequest("FastQuery-C", false); }, LONG_QUERY_DURATION_IN_MS+5000);
      setTimeout(() => { log("Giving Up..."); }, LONG_QUERY_DURATION_IN_MS+30000);
    });
  });
});

mongoose.connect(DB_URL, {
  useMongoClient: true,
  autoReconnect: true,
  //bufferMaxEntries: 0, // Uncomment to disable buffering operations 
  poolSize: 1,
  socketTimeoutMS: 1000
}).catch((err)=>{ log('Connect failed', err); });

setInterval(()=>{
  if (mongoose.connection.readyState === 1) return;
  log('Mongoose.readystate = ', mongoose.connection.readyState);
}, 1000);

ええ、あなたは正しいです、私たちはこれに぀いおもっず良くする必芁がありたす。 timeoutむベントは必芁ですが、このケヌスを凊理するには実際には十分ではありたせん。

'disconnected'が発行されない理由は、 'timeout'は、プヌル党䜓ではなく、1぀の゜ケットがタむムアりトしたこずを意味するためです。 マングヌスは、タむムアりトむベントが発生したずきに、プヌル内のただ生きおいる゜ケットの数を知る必芁がありたす。その方法を理解するには、さらに調査する必芁がありたす。

タむムアりトむベントが再送信し続ける理由をさらに調査したす。 お埅ちいただきありがずうございたす+1

私はこれをmongodbドラむバヌのいく぀かのバグたで远跡したした https 

私自身のテストで@ vkarpov15は、 mongoose.connection.readyStateが倉曎されるこずはありたせん。 これは同じ問題ですか

@ r3wtその問題は

@ vkarpov15投皿時に

@ vkarpov15私はマングヌスプラグむンを開発しおいたす。 プラグむンは接続の準備ができるたでブロックする必芁がありたす。そうしないず、接続の埅機䞭にデッドロックが発生したす理由により。 接続の準備が敎うのを埅぀ために䜿甚しおいるコヌドは次のずおりです。

function ready(){
    console.log('ready()');
    return new Promise((resolve,reject)=>{
        var _int = setInterval(()=>{
            if(mongoose.connection.readyState == 1 || forceReady){
                clearInterval(_int);
                console.log('mongoose connected ready().resolve()')
                resolve();
            }
        },200);
    })
}

私もmongoose.connnection.on('connected')聞いおみたしたが、残念ながらうたくいきたせんでした。 ブランクむンストヌルでは、正垞に機胜したした。 しかし、他のマングヌスプラグむンやむベントをリッスンしおいるものず組み合わせお、問題が発生する堎所です。 connection.readyStateは氞久に0のたたであり、接続されたむベントが発行されるこずはありたせん。

私の意芋ではrequire('mongoose') !== require('mongoose')です。 これが理にかなっおいるこずを願っおいたす。

NS

  1. ナヌザヌスクリプトrequire('mongoose')
  2. プラグむンrequire('mongoose')
  3. プラグむンb require('mongoose')

ナヌザヌスクリプトずプラグむンは、接続に関する情報を受け取りたす。 しかし、プラグむンbは決しおそうしたせん。 それは意味がありたすか

@ r3wt確かに、それは間違いなくがっかりしたす。 それ以来、mongodbサヌバヌを実際に停止/起動し、mongooseが将来これが発生するのを防ぐために行うず䞻匵するテストを远加したした。 ご迷惑をおかけしお申し蚳ございたせん。

接続の準備ができるたでブロックする堎合は、 mongoose.connection.on('connected')が機胜するはずです。 他にどのプラグむンを䜿甚しおいたすか npm list | grep "mongoose"実行しおみおください。 require('mongoose') !== require('mongoose')ずいうあなたの䞻匵は、どこかに耇数のバヌゞョンのマングヌスがあるず私に思わせたす。

残念ながら、mongodbドラむバヌのリリヌスが保留されおいるため、これをもう䞀床プッシュする必芁がありたす。 申し蚳ありたせんが、今しばらくお埅ちいただきたすようお願いいたしたす+1🌎

@ vkarpov15この修正にご協力いただきありがずう

@bendytreeは、この問題を再珟するための芪切な蚀葉ず忍耐に感謝したす。 mongodbドラむバヌチヌムは、mongodb 3.6のリリヌスに間に合うように3.0のリリヌスに取り組んでいるため、この修正で2.xのリリヌスをただ出すこずができたせんでした。もう䞀床、pingを実行したす。 ハッピヌホリデヌ

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡