mongoError: cấu trúc liên kết đã bị phá hủy


163

Tôi có một dịch vụ REST được xây dựng trong node.js với Restify và Mongoose và mongoDB với một bộ sưu tập với khoảng 30.000 tài liệu có kích thước thông thường. Tôi có dịch vụ nút của tôi chạy qua pmx và pm2.

Hôm qua, đột nhiên, nút bắt đầu phát hiện ra lỗi với thông báo "MongoError: Topology đã bị hủy", không còn gì nữa. Tôi không biết điều này có nghĩa là gì và điều gì có thể đã kích hoạt điều này. cũng không có nhiều để được tìm thấy khi google tìm kiếm này. Vì vậy, tôi nghĩ rằng tôi muốn hỏi ở đây.

Sau khi khởi động lại dịch vụ nút ngày hôm nay, các lỗi đã dừng lại. Tôi cũng có một trong số đó đang chạy trong sản xuất và điều đó làm tôi sợ rằng điều này có thể xảy ra bất cứ lúc nào đối với một phần khá quan trọng của thiết lập đang chạy ở đó ...

Tôi đang sử dụng các phiên bản sau của các gói được đề cập:

  • cầy mangut: 4.0.3
  • khôi phục: 3.0.3
  • nút: 0.10.25

2
Tôi đang gặp vấn đề tương tự khi chỉ sử dụng trình điều khiển mongodb :(
0x8890

1
Tôi không sử dụng buồm, vì vậy không, tôi không nghĩ rằng điều đó sẽ khắc phục vấn đề của mình
dreagan

Câu trả lời:


98

Có vẻ như kết nối của máy chủ nút của bạn với phiên bản MongoDB của bạn đã bị gián đoạn trong khi nó đang cố gắng ghi vào nó.

Hãy xem mã nguồn Mongo tạo ra lỗi đó

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);
}

Điều này dường như không liên quan đến vấn đề Sails được trích dẫn trong các bình luận, vì không có bản nâng cấp nào được cài đặt để kết tủa sự cố hoặc "sửa chữa"


2
Tôi có cùng một vấn đề và nó xảy ra gần như mỗi tuần và tắt ứng dụng làm việc với mongo, đây có phải là một số vấn đề tôi tạo ra hay đây là một vấn đề trong mongoose?
Mohammad Ganji

@MohammadGanji: Tôi gặp lỗi này khi không có Mongoose, trong khi gỡ lỗi mã máy khách và không đủ nhanh để bước qua các câu lệnh. Không chắc chắn điều gì gây ra nó, nhưng đặt điểm dừng ngay sau khi truy vấn mongo sẽ tránh được.
Dan Dascalescu

@DanDascalescu Tôi quên đề cập rằng vấn đề của tôi đã được giải quyết, đó là vấn đề với việc đăng nhập, có vẻ như có một số cảnh báo trong nhật ký mà sau đó đã mất khoảng một gigabyte lưu trữ và tắt quy trình mongo, vì vậy tôi đã thử nén và sao lưu và vấn đề đã được giải quyết
Mohammad Ganji

83

Tôi biết rằng câu trả lời của Jason đã được chấp nhận, nhưng tôi gặp vấn đề tương tự với Mongoose và thấy rằng dịch vụ lưu trữ cơ sở dữ liệu của tôi được khuyến nghị áp dụng các cài đặt sau để duy trì kết nối của Mongodb trong sản xuất:

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

Tôi hy vọng rằng câu trả lời này có thể giúp những người khác có lỗi "Topology bị phá hủy".


4
Điều này đã không khắc phục vấn đề cho tôi. Tôi thực sự đã kết thúc việc tăng keepAlive của mình lên 30000, điều này đã giúp ích rất nhiều. Mặc dù tôi vẫn nhận được lỗi cấu trúc liên tục thỉnh thoảng đến.
ifightcrime

9
sử dụng trình điều khiển Mongo từ phiên bản 3.4.2, các tùy chọn này cần phải ở cấp cao nhất: tùy chọn: {keepAlive: 1, connectTimeoutMS: 30000, recconnectectTries: 30, recconnectectInterval: 5000}
Sebastien H.

Tôi gặp lỗi này mà không có Mongoose, trong khi gỡ lỗi mã máy khách và không đủ nhanh để bước qua các câu lệnh. Không chắc chắn điều gì gây ra nó, nhưng đặt điểm dừng ngay sau khi truy vấn mongo sẽ tránh được.
Dan Dascalescu

76

Lỗi này là do trình điều khiển mongo bị rớt kết nối vì bất kỳ lý do gì (ví dụ: máy chủ không hoạt động).

Theo mặc định, cầy mangut sẽ cố gắng kết nối lại trong 30 giây sau đó dừng thử lại và ném lỗi mãi cho đến khi khởi động lại.

Bạn có thể thay đổi điều này bằng cách chỉnh sửa 2 trường này trong các tùy chọn kết nối

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

tài liệu tùy chọn kết nối


3
Vâng. Về mặt kỹ thuật, câu trả lời được chấp nhận trả lời câu hỏi được hỏi NHƯNG đây là cách đúng đắn để tránh kịch bản đang thảo luận.
kingdango

3
sử dụng trình điều khiển Mongo từ phiên bản 3.4.2, các tùy chọn này cần phải ở cấp cao nhất: tùy chọn: {keepAlive: 1, connectTimeoutMS: 30000, recconnectectTries: 30, recconnectectInterval: 2000}
Sebastien H.

1
Để làm rõ, theo tài liệu của Trình điều khiển Node MongoDB , theo mặc định, máy chủ sẽ cố gắng kết nối lại 30 lần, cách nhau một giây giữa mỗi lần thử lại.
Boaz

4
Bây giờ bạn không cần cung cấp các tùy chọn này dưới đối tượng máy chủ. Nó đi trực tiếp đến các đối tượng tùy chọn.
Animesh Singh

3
Chỉ muốn thêm rằng các phiên bản gần đây của cầy mangut có các tùy chọn đó ở cấp cao nhất, vì vậy không cần thêm server: {v.v.
Alex K

17

Trong trường hợp của tôi, lỗi này là do db.close();phần 'chờ đợi' bên trong 'async'

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
Trong trường hợp của Carlos, tôi đoán sự gần gũi đã xảy ra trước mọi thứ khác. Trường hợp của tôi cũng tương tự: Tôi đã truy cập DB sau khi đóng nó. Sẽ thật tuyệt nếu các nhà phát triển Mongo có thể tạo ra các thông báo lỗi rõ ràng hơn. "Cấu trúc liên kết bị hỏng" nghe giống như một ghi chú nội bộ.
Juan Lanus

3
giải pháp của bạn là di chuyển db.closevào một thenkhối, phải không?
AlexChaffee

Điều đó đúng, trong trường hợp của tôi, tôi chỉ xóa dòng db.close (), nhưng di chuyển nó vào một khối sau đó dường như là một giải pháp tốt.
Carlos Rodríguez

1
Di chuyển db.closeđến một thenkhối làm việc rất tốt đối với tôi với trình điều khiển MongoDB Node.js bản địa.
kevinmicke

12

Chỉ là một bổ sung nhỏ cho câu trả lời của Gaafar, nó đã cho tôi một cảnh báo không dùng nữa. Thay vì trên đối tượng máy chủ, như thế này:

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

Nó có thể đi vào đối tượng cấp cao nhất. Về cơ bản, chỉ cần lấy nó ra khỏi đối tượng máy chủ và đặt nó vào đối tượng tùy chọn như thế này:

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

7

"Cấu trúc liên kết đã bị hủy" có thể được gây ra bởi việc ngắt kết nối trước khi lập chỉ mục tài liệu mongo được tạo, theo nhận xét này

Để đảm bảo tất cả các mô hình đều được tạo chỉ mục trước khi ngắt kết nối, bạn có thể:

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

await mongoose.disconnect();

cảm ơn bạn, nếu bạn đang chạy các trường hợp thử nghiệm - đây có lẽ là một câu trả lời rất có thể ...
Nick H247

1
Đây là nó cho tôi. Cảm ơn bạn! Tôi đã chạy thử nghiệm trong Jest với mongodb-memory-server, nhận được các lỗi lẻ tẻ về cấu trúc liên kết hoặc xử lý mở / Lời hứa chưa hoàn thành. Nhưng đôi khi nó làm việc. Thêm một sự chờ đợi vào các chỉ mục đã cố định nó.
cướp

Tôi gặp lỗi này mà không có Mongoose, trong khi gỡ lỗi mã Jest như @robledle và không đủ nhanh để bước qua các câu lệnh. Không chắc chắn điều gì gây ra nó, nhưng đặt điểm dừng ngay sau khi truy vấn mongo sẽ tránh được.
Dan Dascalescu

@robledle cuối cùng bạn đã sửa nó như thế nào? Tôi vừa gặp phải vấn đề này và nó khiến tôi không thể kết nối lại với MongoDB. Tôi đã xóa mọi thứ và cài đặt lại MongoDB (thông qua homebrew) và bây giờ nó sẽ không chạy khi khởi động nữa. (Có thể là một vấn đề không liên quan)
bboyz

Âm thanh không liên quan. Ứng dụng của tôi hoạt động tốt nhưng thử nghiệm thất bại.
cướp

3

Nhận xét của Sebastian về câu trả lời của Adrien cần được chú ý nhiều hơn, nó đã giúp tôi nhưng nó là một bình luận đôi khi có thể bị bỏ qua vì vậy đây là một giải pháp :

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

Tôi đã có cùng một lỗi. Cuối cùng, tôi thấy rằng tôi có một số lỗi về mã của tôi. Tôi sử dụng cân bằng tải cho hai máy chủ nodejs, nhưng tôi chỉ cập nhật mã của một máy chủ.

Tôi thay đổi máy chủ mongod của mình from standalone to replication, nhưng tôi quên thực hiện cập nhật tương ứng cho chuỗi kết nối, vì vậy tôi đã gặp lỗi này.

chuỗi kết nối độc lập: mongodb://server-1:27017/mydb chuỗi kết nối sao chép: mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicaSet=myReplSet

chi tiết tại đây, [tài liệu mongo cho chuỗi kết nối]


2

Tôi đã gặp điều này trong môi trường kubernetes / minikube + nodejs + mongoose. Vấn đề là dịch vụ DNS gặp phải một loại độ trễ. Kiểm tra DNS đã sẵn sàng giải quyết vấn đề của tôi.

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
};

(các số trong db_options là tùy ý được tìm thấy trên stackoverflow và tương tự như các trang web)


2

Ở đây những gì tôi đã làm, nó hoạt động tốt. Vấn đề đã biến mất sau khi thêm các tùy chọn dưới đây.

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

Bạn cần khởi động lại mongo để giải quyết lỗi cấu trúc liên kết, sau đó chỉ cần thay đổi một số tùy chọn của cầy mangut hoặc mongoclient để khắc phục vấn đề này:

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

mongoose.connect(mongoDevString,mongoOptions);

Chào mừng đến với SO! Vui lòng chỉnh sửa câu trả lời của bạn và thêm một số thông tin, tức là cách giải quyết vấn đề, để được hướng dẫn thêm, hãy xem stackoverflow.com/help/how-to-ask
B - rian

1

Tôi đã gặp lỗi này, trong khi tôi đang tạo một cơ sở dữ liệu mới trên Cộng đồng La bàn MongoDb của mình. Vấn đề là với Mongod của tôi, nó không chạy. Vì vậy, để khắc phục, tôi phải chạy lệnh Mongod như trước.

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

Tôi đã có thể tạo một cơ sở dữ liệu sau khi chạy lệnh đó.

Hy vọng nó giúp.


1

Tôi đã vật lộn với điều này một thời gian - Như bạn có thể thấy từ các câu trả lời khác, vấn đề có thể rất khác.

Cách dễ nhất để tìm hiểu những gì gây ra là điều này là bật loggerLevel: 'info'trong các tùy chọn


0

Trong trường hợp của tôi, lỗi này là do một máy chủ giống hệt đã chạy nền.

Điều kỳ lạ là khi tôi khởi động máy chủ của mình mà không nhận thấy có một máy nào đang chạy, bảng điều khiển không hiển thị bất cứ thứ gì như 'cái gì đó đang sử dụng cổng xxx'. Tôi thậm chí có thể tải lên một cái gì đó lên máy chủ. Vì vậy, tôi đã mất khá nhiều thời gian để xác định vấn đề này.

Hơn nữa, sau khi đóng tất cả các ứng dụng tôi có thể tưởng tượng, tôi vẫn không thể tìm thấy quy trình sử dụng cổng này trong trình giám sát hoạt động của máy Mac. Tôi phải sử dụng lsofđể theo dõi. Thủ phạm không gây ngạc nhiên - đó là một quá trình nút. Tuy nhiên, với PID được hiển thị trong thiết bị đầu cuối, tôi thấy số cổng trong màn hình khác với số được sử dụng bởi máy chủ của tôi.

Tất cả trong tất cả, giết tất cả các quá trình nút có thể giải quyết vấn đề này trực tiếp.


-3

Tôi đã giải quyết vấn đề này bằng cách:

  1. đảm bảo mongo đang chạy
  2. khởi động lại máy chủ của tôi

4
Điều này không ngăn sự cố xảy ra lần nữa
Sam Munroe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.