mongoError : 토폴로지가 파괴되었습니다


163

Restify 및 Mongoose를 사용하여 node.js에 내장 된 REST 서비스와 약 30.000 개의 일반 크기 문서가있는 mongoDB가 있습니다. pmx와 pm2를 통해 노드 서비스를 실행하고 있습니다.

어제 갑자기 노드가 "MongoError : Topology was destroyed"메시지와 함께 오류를 크 래핑하기 시작했습니다. 나는 이것이 무엇을 의미하는지, 그리고 무엇이 이것을 유발할 수 있었는지 전혀 모른다. 구글 검색시 찾을 것도 많지 않습니다. 그래서 여기에 물어볼 줄 알았습니다.

오늘 노드 서비스를 다시 시작한 후 오류가 발생하는 것을 막았습니다. 나는 또한 프로덕션에서 이러한 중 하나를 실행하고 있으며 주어진 시간 에이 부분에서 실행되는 설정의 매우 중요한 부분에서 이것이 발생할 수 있다는 것을 두려워합니다 ...

언급 된 패키지의 다음 버전을 사용하고 있습니다.

  • 몽구스 : 4.0.3
  • 재확인 : 3.0.3
  • 노드 : 0.10.25

2
mongodb 드라이버 만 사용하여 비슷한 문제를 겪고 있습니다. (
0x8890

1
나는 돛을 사용하지 않기 때문에, 나는 그것이 내 문제를 해결할 것이라고 생각하지 않는다
dreagan

답변:


98

그것은 MongoDB 인스턴스에 대한 노드 서버의 연결이 중단되는 것을 의미합니다.

해당 오류를 생성하는 Mongo 소스 코드를 살펴보십시오.

Mongos.prototype.insert = function(ns, ops, options, callback) {
    if(typeof options == 'function') callback = options, options = {};
    if(this.s.state == DESTROYED) return callback(new MongoError(f('topology was destroyed')));
    // Topology is not connected, save the call in the provided store to be
    // Executed at some point when the handler deems it's reconnected
    if(!this.isConnected() && this.s.disconnectHandler != null) {
      callback = bindToCurrentDomain(callback);
      return this.s.disconnectHandler.add('insert', ns, ops, options, callback);
    }

    executeWriteOperation(this.s, 'insert', ns, ops, options, callback);
}

충돌이나 "수정"을 촉진하기 위해 업그레이드가 설치되지 않았기 때문에 주석에 인용 된 Sails 문제와 관련이없는 것으로 보입니다.


2
나는 같은 문제가 있으며 거의 ​​매주 발생하며 몽고와 함께 작동하는 응용 프로그램을 종료합니다.이 문제가 발생합니까 아니면 몽구스 문제입니까?
Mohammad Ganji

@MohammadGanji : 클라이언트 코드를 디버깅하고 명령문을 스테핑 할 때 충분히 빠르지 않은 동안 Mongoose 없이이 오류가 발생합니다. 원인이 무엇인지 확실하지 않지만 mongo 쿼리가 중단 된 직후 중단 점을 설정하십시오.
Dan Dascalescu

@ DanDascalescu 내 문제가 해결되었다는 것을 잊어 버렸습니다. 로깅에 문제가 있습니다. 로그에 약간의 기가 바이트의 스토리지가 필요하고 몽고 프로세스를 종료 한 후 로그에 약간의 경고가있는 것처럼 보였으므로 압축 및 백업을 시도했습니다. 문제가 해결
모하마드 간지

83

Jason의 대답은 받아 들였지만 Mongoose와 같은 문제가 있었고 내 데이터베이스를 호스팅하는 서비스가 Mongodb의 연결을 프로덕션 환경 에서 유지하기 위해 다음 설정을 적용하는 것이 좋습니다 .

var options = {
  server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
  replset: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } }
};
mongoose.connect(secrets.db, options);

이 답변이 "Topology was destroyed"오류가있는 다른 사람들에게 도움이되기를 바랍니다.


4
이것은 나를 위해 문제를 해결하지 못했습니다. 실제로 keepAlive를 30000으로 늘리는 데 큰 도움이되었습니다. 여전히 가끔 토폴로지 오류가 발생하더라도 여전히 발생합니다.
ifightcrime

9
버전 3.4.2의 Mongo 드라이버를 사용하는 경우 이러한 옵션은 최상위 레벨에 있어야합니다. 옵션 : {keepAlive : 1, connectTimeoutMS : 30000, reconnectTries : 30, reconnectInterval : 5000}
Sebastien H.

클라이언트 코드를 디버깅하고 명령문을 스테핑하는 데 충분하지 않은 동안 Mongoose 없이이 오류가 발생합니다. 원인이 무엇인지 확실하지 않지만 mongo 쿼리가 중단 된 직후 중단 점을 설정하십시오.
Dan Dascalescu

76

이 오류는 mongo 드라이버가 어떤 이유로 든 연결을 끊기 때문에 발생합니다 (예 : 서버가 다운 됨).

기본적으로 mongoose는 30 초 동안 다시 연결을 시도한 후 다시 시도를 중지하고 다시 시작할 때까지 영원히 오류를 발생시킵니다.

연결 옵션에서이 2 개의 필드를 편집하여이를 변경할 수 있습니다

mongoose.connect(uri, 
    { server: { 
        // sets how many times to try reconnecting
        reconnectTries: Number.MAX_VALUE,
        // sets the delay between every retry (milliseconds)
        reconnectInterval: 1000 
        } 
    }
);

연결 옵션 설명서


3
네. 기술적으로 허용 된 답변은 묻는 질문에 대답하지만 이것이 토론중인 시나리오를 피하는 올바른 방법입니다.
kingdango

3
버전 3.4.2의 Mongo 드라이버를 사용하는 경우이 옵션은 최상위 레벨이어야합니다. 옵션 : {keepAlive : 1, connectTimeoutMS : 30000, reconnectTries : 30, reconnectInterval : 2000}
Sebastien H.

1
명확히하기 위해 Node MongoDB Driver문서에 따르면 기본적으로 서버는 각 재시도 사이에 1 초 간격으로 30 번 다시 연결을 시도합니다.
보아스

4
지금 서버 객체 아래에 이러한 옵션을 제공 할 필요는 없습니다. 옵션 개체로 직접 이동합니다.
Animesh Singh

3
몽구스의 최신 버전에는 이러한 옵션이 최상위 레벨에 있으므로 추가 할 필요가 없습니다 server: {.
Alex K

17

필자의 경우이 오류는 db.close();'비동기'내 '대기'섹션 이 부족하여 발생했습니다.

MongoClient.connect(url, {poolSize: 10, reconnectTries: Number.MAX_VALUE, reconnectInterval: 1000}, function(err, db) {
    // Validate the connection to Mongo
    assert.equal(null, err);    
    // Query the SQL table 
    querySQL()
    .then(function (result) {
        console.log('Print results SQL');
        console.log(result);
        if(result.length > 0){

            processArray(db, result)
            .then(function (result) {
                console.log('Res');
                console.log(result);
            })
            .catch(function (err) {
                console.log('Err');
                console.log(err);
            })
        } else {
            console.log('Nothing to show in MySQL');
        }
    })
    .catch(function (err) {
        console.log(err);
    });
    db.close(); // <--------------------------------THIS LINE
});

2
카를로스의 경우에 나는 모든 것이 끝나기 전에 종결이 일어난 것 같아 제 경우도 비슷했습니다. DB를 닫은 후 DB에 액세스했습니다. Mongo 개발자가보다 명확한 오류 메시지를 생성 할 수 있다면 좋을 것입니다. "Topology broken"은 내부 메모처럼 들립니다.
Juan Lanus

3
솔루션은 이동하는 것이었다 db.closethen오른쪽 블록?
AlexChaffee

내 경우에는 db.close () 줄만 삭제하지만 다음 블록으로 이동하면 좋은 해결책 인 것 같습니다.
카를로스 로드리게스

1
네이티브 MongoDB Node.js 드라이버 db.close를 사용하여 then블록으로 이동하면 효과적이었습니다.
kevinmicke 19 :

12

Gaafar의 대답에 사소한 추가 사항으로 인해 사용 중단 경고가 표시되었습니다. 서버 객체 대신 다음과 같이하십시오.

MongoClient.connect(MONGO_URL, {
    server: {
        reconnectTries: Number.MAX_VALUE,
        reconnectInterval: 1000
    }
});

최상위 개체로 이동할 수 있습니다. 기본적으로 서버 객체에서 꺼내어 다음과 같이 옵션 객체에 넣으십시오.

MongoClient.connect(MONGO_URL, {
    reconnectTries: Number.MAX_VALUE,
    reconnectInterval: 1000
});

7

이 주석에 따라 몽고 문서 색인을 작성하기 전에 몽구스 연결이 끊어져 "토폴로지가 손상되었습니다"가 발생할 수 있습니다 .

연결을 끊기 전에 모든 모델의 색인이 작성되도록하기 위해 다음을 수행 할 수 있습니다.

await Promise.all(mongoose.modelNames().map(model => mongoose.model(model).ensureIndexes()));

await mongoose.disconnect();

테스트 케이스를 실행하는 경우 감사합니다. 아마도이 질문에 대한 답이 될 것입니다 ...
Nick H247

1
이것은 나를위한 것이었다. 감사합니다! mongodb-memory-server로 Jest에서 테스트를 실행하여 토폴로지 또는 열린 핸들 / 미완성 된 약속에 산발적 인 오류가 발생했습니다. 그러나 때로는 효과가있었습니다. 인덱스에 대기를 추가하면 문제가 해결되었습니다.
roblingle

@roblingle과 같은 Jest 코드를 디버깅하고 명령문을 스테핑 할 때 충분히 빠르지 않은 동안 Mongoose 없이이 오류가 발생합니다. 원인이 무엇인지 확실하지 않지만 mongo 쿼리가 중단 된 직후 중단 점을 설정하십시오.
Dan Dascalescu

@ roblingle 어떻게 고치셨습니까? 방금이 문제가 발생하여 MongoDB에 다시 연결할 수 없었습니다. 나는 모든 것을 삭제하고 MongoDB (homebrew를 통해)를 다시 설치했으며 이제는 더 이상 시작시 실행되지 않습니다. (관련이없는 문제 일 수 있음)
bobbyz

관련이 없습니다. 내 앱은 정상적으로 작동했지만 테스트에 실패했습니다.
roblingle

3

Adrien의 답변에 대한 Sebastian의 의견은 더 많은 관심을 필요로하지만 도움이되는 의견은 언젠가 무시 될 수 있으므로 여기에 해결책이 있습니다 .

var options =  { useMongoClient: true, keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 5000 }
mongoose.connect(config.mongoConnectionString, options, (err) => {
    if(err) {
        console.error("Error while connecting", err);
    }
});

2

나는 또한 같은 오류가 있었다. 마지막으로 코드에 오류가 있음을 발견했습니다. 두 개의 nodejs 서버에 대해 부하 분산을 사용하지만 한 서버의 코드 만 업데이트합니다.

mongod server를 변경 from standalone to replication했지만 연결 문자열에 해당하는 업데이트를 수행하는 것을 잊어 버렸 으므로이 오류가 발생했습니다.

독립형 연결 문자열 : mongodb://server-1:27017/mydb 복제 연결 문자열 : mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicaSet=myReplSet

자세한 내용은 여기 : [연결 문자열에 대한 mongo doc]


2

나는 kubernetes / minikube + nodejs + mongoose 환경에서 이것을 만났습니다. 문제는 DNS 서비스가 일종의 대기 시간으로 가동되었다는 것입니다. DNS 확인 준비가되어 내 문제가 해결되었습니다.

const dns = require('dns');

var dnsTimer = setInterval(() => {
	dns.lookup('mongo-0.mongo', (err, address, family) => {
		if (err) {
			console.log('DNS LOOKUP ERR', err.code ? err.code : err);
		} else {
			console.log('DNS LOOKUP: %j family: IPv%s', address, family);
			clearTimeout(dnsTimer);
			mongoose.connect(mongoURL, db_options);
		}
	});
}, 3000);


var db = mongoose.connection;
var db_options = {
	autoReconnect:true,

	poolSize: 20,
	socketTimeoutMS: 480000,
	keepAlive: 300000,

	keepAliveInitialDelay : 300000,
	connectTimeoutMS: 30000,
	reconnectTries: Number.MAX_VALUE,
	reconnectInterval: 1000,
	useNewUrlParser: true
};

(db_options의 숫자는 stackoverflow에서 임의로 발견되며 사이트와 유사합니다)


2

여기 내가 한 일은 잘 작동합니다. 아래 옵션을 추가 한 후 문제가 발생했습니다.

const dbUrl = "mongodb://localhost:27017/sampledb";
const options =  { useMongoClient: true, keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 5000, useNewUrlParser: true }
mongoose.connect(dbUrl,options, function(
  error
) {
  if (error) {
    console.log("mongoerror", error);
  } else {
    console.log("connected");
  }

});

2

토폴로지 오류를 해결하려면 mongo를 다시 시작한 다음 mongoose 또는 mongoclient의 일부 옵션을 변경하여이 문제를 극복하십시오.

var mongoOptions = {
    useMongoClient: true,
    keepAlive: 1,
    connectTimeoutMS: 30000,
    reconnectTries: Number.MAX_VALUE,
    reconnectInterval: 5000,
    useNewUrlParser: true
}

mongoose.connect(mongoDevString,mongoOptions);

SO에 오신 것을 환영합니다! 답변을 편집하고 더 많은 정보, 즉 문제 해결 방법을 추가하십시오. 자세한 지침은 stackoverflow.com/help/how-to-ask
B--rian

1

MongoDb Compass Community에서 새 데이터베이스를 작성하는 동안이 오류가 발생했습니다. 문제는 내 Mongod와 관련이 있으며 실행되지 않았습니다. 그래서 수정 사항으로, 앞에서와 같이 Mongod 명령을 실행해야했습니다.

C:\Program Files\MongoDB\Server\3.6\bin>mongod

해당 명령을 실행 한 후 데이터베이스를 만들 수있었습니다.

도움이 되길 바랍니다.


1

나는 이것을 한동안 고투하고 있었다-다른 답변에서 볼 수 있듯이 문제는 매우 다를 수 있습니다.

원인을 찾는 가장 쉬운 방법 loggerLevel: 'info'은 옵션 을 켜는 것입니다 .


0

필자의 경우이 오류는 백그라운드에서 이미 실행중인 동일한 서버 인스턴스로 인해 발생했습니다.

이상한 점은 이미 실행중인 서버가 있음을 알리지 않고 서버를 시작했을 때 콘솔에 '뭔가 포트 xxx를 사용하고 있습니다'와 같은 것을 표시하지 않았습니다. 서버에 무언가를 업로드 할 수도 있습니다. 따라서이 문제를 찾는 데 시간이 오래 걸렸습니다.

또한 상상할 수있는 모든 응용 프로그램을 닫은 후에도 여전히 Mac의 활동 모니터 에서이 포트를 사용하는 프로세스를 찾을 수 없습니다. lsof추적하는 데 사용해야 합니다. 범인은 놀랄 일이 아니 었습니다. 그것은 노드 프로세스입니다. 그러나 터미널에 표시된 PID로 모니터의 포트 번호가 서버에서 사용되는 포트 번호와 다릅니다.

대체로 모든 노드 프로세스를 종료하면이 문제를 직접 해결할 수 있습니다.


-3

이 문제를 다음과 같이 해결했습니다.

  1. 몽고가 실행되고 있는지 확인
  2. 내 서버를 다시 시작

4
그렇다고해서 문제가 다시 발생하는 것을 막을 수는 없습니다
Sam Munroe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.