问题
Althought this question was asked more than one year ago, it's still relevant for me. I'm also trying to provide more information to make this not just a duplicate. As stated in the original question - if you connect to a MongoDB database with Mongoose and the connection fails, the callback gets called with an error but the whole connection attempt thingy is still somehow running in the background (and not being closed) and your script does not terminate.
So this example ...
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/database', function(err) {
if (err) {
console.log("error");
mongoose.disconnect(); // Obviously does nothing, because mongoose.connection.readyState prevents any action.
return;
}
console.log("success");
mongoose.disconnect();
});
... prints "success" and terminates if the MongoDB server is already running before this gets executed and prints "error" and keeps running forever if the MongoDB server is not available from the beginning. Here's the console output of the MongoDB server with a successful execution of the above code (poolSize = 5
) with looks ok so far:
2016-01-07T04:15:24.385+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58873 #1 (1 connection now open)
2016-01-07T04:15:24.385+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58874 #2 (2 connections now open)
2016-01-07T04:15:24.385+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58875 #3 (3 connections now open)
2016-01-07T04:15:24.386+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58876 #4 (4 connections now open)
2016-01-07T04:15:24.386+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58877 #5 (5 connections now open)
2016-01-07T04:15:24.403+0100 I NETWORK [conn1] end connection 127.0.0.1:58873 (4 connections now open)
2016-01-07T04:15:24.403+0100 I NETWORK [conn2] end connection 127.0.0.1:58874 (3 connections now open)
2016-01-07T04:15:24.403+0100 I NETWORK [conn3] end connection 127.0.0.1:58875 (2 connections now open)
2016-01-07T04:15:24.404+0100 I NETWORK [conn4] end connection 127.0.0.1:58876 (1 connection now open)
2016-01-07T04:15:24.404+0100 I NETWORK [conn5] end connection 127.0.0.1:58877 (0 connections now open)
Now what makes this "no termination on error" thing a problem is that the connection attempts are still somehow active even if the callback gets called with e.g. an ECONNREFUSED
error. And that is causing trouble for me.
Due to the fact that the automatic Mongoose reconnection handling does not take place at the first (failed) connection I wanted to write my own "wait for the MongoDB server if it's not currently running" script like shown here.
My version:
var mongoose = require('mongoose');
function connect() {
mongoose.connect('mongodb://localhost/database', function(err) {
if (err) {
console.log("error");
mongoose.disconnect();
setTimeout(connect, 5000);
return;
}
console.log("success");
mongoose.disconnect();
});
}
connect();
What happens is that each time the connect(...)
method gets called a bunch of new connections are created to the MongoDB server. And even though the callback got called with an error, these connection attempts are still active. I can verify this by starting the MongoDB server after e.g. the first failing connection attempt and what I'll get in the log after 5 seconds is the following:
2016-01-07T04:23:07.501+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58893 #1 (1 connection now open)
2016-01-07T04:23:07.501+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58894 #2 (2 connections now open)
2016-01-07T04:23:07.503+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58895 #3 (3 connections now open)
2016-01-07T04:23:07.503+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58896 #4 (4 connections now open)
2016-01-07T04:23:07.504+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58897 #5 (5 connections now open)
2016-01-07T04:23:09.499+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58898 #6 (6 connections now open)
2016-01-07T04:23:09.500+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58899 #7 (7 connections now open)
2016-01-07T04:23:09.501+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58900 #8 (8 connections now open)
2016-01-07T04:23:09.503+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58901 #9 (9 connections now open)
2016-01-07T04:23:09.503+0100 I NETWORK [initandlisten] connection accepted from 127.0.0.1:58902 #10 (10 connections now open)
2016-01-07T04:23:09.515+0100 I NETWORK [conn6] end connection 127.0.0.1:58898 (9 connections now open)
2016-01-07T04:23:09.516+0100 I NETWORK [conn7] end connection 127.0.0.1:58899 (8 connections now open)
2016-01-07T04:23:09.516+0100 I NETWORK [conn8] end connection 127.0.0.1:58900 (7 connections now open)
2016-01-07T04:23:09.516+0100 I NETWORK [conn9] end connection 127.0.0.1:58901 (6 connections now open)
2016-01-07T04:23:09.517+0100 I NETWORK [conn10] end connection 127.0.0.1:58902 (5 connections now open)
And also as you can see only the successfull connections get disconnected by the mongoose.disconnect()
call after logging "success" to the console. I think this is especially a problem because if the MongoDB server does not start within 5 seconds after the script but e.g. with a few minutes delay, the maximum number of possible connections could be exceeded with half-open/unknown/zombie connections. And due to the fact that my script should be running for some days, having some random zombie connections alive for days should not be considered acceptable.
Is this a bug in Mongoose, the MongoDB native driver or am I doing something wrong?
EDIT:
I digged even deeper into this issue and found out that this (see 1. further down) is the place in mongodb-core/the MongoDB Core Driver where the connection/sockets to MongoDB are created. I added debug outputs here (see 2.) and here (see 3.) like this:
- github.com/christkv/mongodb-core/blob/master/lib/connection/connection.js
- github.com/christkv/mongodb-core/blob/master/lib/connection/connection.js#L140
- github.com/christkv/mongodb-core/blob/master/lib/connection/connection.js#L376
(Sorry, I'm only allowed to post 2 links with my reputation being < 10. Maybe someone can edit the links into the text. :>)
// ... [L138]
var closeHandler = function(self) {
console.log("socket: close"); // <--
return function(hadError) {
// ... [L141]
// ... [L374]
self.connection.on('connect', function() {
console.log("socket: connect"); // <--
// Set socket timeout instead of connection timeout
self.connection.setTimeout(self.socketTimeout);
// ... [L378]
In the case of a successful connection of the above example script I expected 5 sockets to be connected - so I thought of following (expected) output:
socket: connect
socket: connect
socket: connect
socket: connect
socket: connect
success
What I got was:
socket: close
socket: close
socket: close
socket: close
socket: close
socket: connect
socket: connect
socket: connect
socket: connect
socket: connect
success
Why would the sockets emit close
events before they connect successfully in context with the MongoDB driver/mongoose libraries/modules?
Because if I do the following (MongoDB server already running) ...
var net = require('net');
var socket = net.createConnection(27017, 'localhost');
socket.on('close', function() {
console.log("socket: close");
});
socket.on('connect', function() {
console.log("socket: connect");
});
... the log satisfies my expectations:
socket: connect
I know it's a very long question. I already appreciate if you read until here/the end.
来源:https://stackoverflow.com/questions/34650524/node-js-mongoose-mongodb-sockets-of-failed-initial-connection-attempts-are-stil