You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置网络访问后本地服务器仍无法稳定连接MongoDB

本地服务器连接MongoDB Atlas后频繁断开的排查与解决

我开发的项目需要同时从Heroku服务器和本地开发服务器连接MongoDB实例,Heroku端连接交互正常,但本地服务器连接建立后很快断开,无手动终止或未处理异常导致进程崩溃的情况。已将MongoDB Atlas网络访问配置为0.0.0.0/0允许任意IP访问,问题仍存在。

相关代码

db.js

const mongoose = require("mongoose");

mongoose.set("strictQuery", true);

const isDev = process.env.NODE_ENV !== "production";
const dbURI = process.env.MONGODB_URI;

mongoose.connect(dbURI, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

mongoose.connection.on("connected", () => {
  console.log("MongoDB connection established!");
});

mongoose.connection.on("error", (error) => {
  console.error(`MongoDB connection error: ${error}`);
  process.exit(-1);
});

//New Unhandled exceptions method
mongoose.connection.on("disconnected", (error) => {
  if (error) {
    console.error(`MongoDB connection disconnected: ${error}`);
    process.exit(-1);
  } else {
    console.log(error);
    process.exit(0);
  }
});

// Handle SIGINT event for graceful shutdown
process.on("SIGINT", (err) => {
  if (err) {
    console.error(err);
  }
  connection.close(() => {
    console.log("MongoDB connection closed due to app termination");
    process.exit(0);
  });
});

server.js

// Load the required packages
const express = require("express");
const nodemon = require("nodemon");
const dotenv = require("dotenv");
const cors = require("cors");

// Load the environment variables from the .env file
dotenv.config();

// Initial database connection
const db = require("./data/db");

// Import routes
const linkButtonRoute = require("./routes/linkButtonRoute");

// Create an express app
const app = express();

app.set("view engine", "ejs");

// Use the express.json() middleware to parse incoming request bodies
app.use(express.json());

app.use(cors());

// Set the port for the application
const port = process.env.PORT || 5000;

// Mount the routes to the express app
app.use("/api/linkButton", linkButtonRoute);


// Start the server
app.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

报错日志

C:\Users\Lior\AppBar-Server\node-js-getting-started\node_modules\mongoose\lib\connection.js:825
  const serverSelectionError = new ServerSelectionError();
                               ^

MongooseServerSelectionError: connect ETIMEDOUT 15.185.70.41:27017
    at Connection.openUri (C:\Users\Lior\AppBar-Server\node-js-getting-started\node_modules\mongoose\lib\connection.js:825:32)
    at C:\Users\Lior\AppBar-Server\node-js-getting-started\node_modules\mongoose\lib\index.js:419:10
    at C:\Users\Lior\AppBar-Server\node-js-getting-started\node_modules\mongoose\lib\helpers\promiseOrCallback.js:41:5
    at new Promise (<anonymous>)
    at promiseOrCallback (C:\Users\Lior\AppBar-Server\node-js-getting-started\node_modules\mongoose\lib\helpers\promiseOrCallback.js:40:10)
    at Mongoose._promiseOrCallback (C:\Users\Lior\AppBar-Server\node-js-getting-started\node_modules\mongoose\lib\index.js:1272:10)
    at Mongoose.connect (C:\Users\Lior\AppBar-Server\node-js-getting-started\node_modules\mongoose\lib\index.js:418:20)
    at Object.<anonymous> (C:\Users\Lior\AppBar-Server\node-js-getting-started\data\db.js:8:10)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10) {
  reason: TopologyDescription {
    type: 'ReplicaSetNoPrimary',
    servers: Map(3) {
      'ac-0qzaeb7-shard-00-02.nxgkbuq.mongodb.net:27017' => ServerDescription {
        address: 'ac-0qzaeb7-shard-00-02.nxgkbuq.mongodb.net:27017',
        type: 'Unknown',
        hosts: [],
        passives: [],
        arbiters: [],
        tags: {},
        minWireVersion: 0,
        maxWireVersion: 0,
        roundTripTime: -1,
        lastUpdateTime: 183346427,
        lastWriteDate: 0,
        error: MongoNetworkError: connect ETIMEDOUT 15.185.70.41:27017
            at connectionFailureError (C:\Users\Lior\AppBar-Server\node-js-getting-started\node_modules\mongodb\lib\cmap\connect.js:387:20)
            at TLSSocket.<anonymous> (C:\Users\Lior\AppBar-Server\node-js-getting-started\node_modules\mongodb\lib\cmap\connect.js:310:22)
            at Object.onceWrapper (node:events:628:26)
            at TLSSocket.emit (node:events:513:28)
            at emitErrorNT (node:internal/streams/destroy:151:8)
            at emitErrorCloseNT (node:internal/streams/destroy:116:3)
            at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
          cause: Error: connect ETIMEDOUT 15.185.70.41:27017
              at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1300:16) {
            errno: -4039,
            code: 'ETIMEDOUT',
            syscall: 'connect',
            address: '15.185.70.41',
            port: 27017
          },
          [Symbol(errorLabels)]: Set(1) { 'ResetPool' }
        },
        topologyVersion: null,
        setName: null,
        setVersion: null,
        electionId: null,
        logicalSessionTimeoutMinutes: null,
        primary: null,
        me: null,
        '$clusterTime': null
      },
      'ac-0qzaeb7-shard-00-00.nxgkbuq.mongodb.net:27017' => ServerDescription {
        address: 'ac-0qzaeb7-shard-00-00.nxgkbuq.mongodb.net:27017',
        type: 'RSSecondary',
        hosts: [
          'ac-0qzaeb7-shard-00-00.nxgkbuq.mongodb.net:27017',
          'ac-0qzaeb7-shard-00-01.nxgkbuq.mongodb.net:27017',
          'ac-0qzaeb7-shard-00-02.nxgkbuq.mongodb.net:27017'
        ],
        passives: [],
        arbiters: [],
        tags: {
          region: 'ME_SOUTH_1',
          nodeType: 'ELECTABLE',
          provider: 'AWS',
          workloadType: 'OPERATIONAL'
        },
        minWireVersion: 0,
        maxWireVersion: 17,
        roundTripTime: 321.9200000000001,
        lastUpdateTime: 183346522,
        lastWriteDate: 2023-05-23T13:11:54.000Z,
        error: null,
        topologyVersion: {
          processId: ObjectId { [Symbol(id)]: [Buffer [Uint8Array]] },
          counter: 11
        },
        setName: 'atlas-yyc43k-shard-0',
        setVersion: 2,
        electionId: null,
        logicalSessionTimeoutMinutes: 30,
        primary: 'ac-0qzaeb7-shard-00-02.nxgkbuq.mongodb.net:27017',
        me: 'ac-0qzaeb7-shard-00-00.nxgkbuq.mongodb.net:27017',
        '$clusterTime': {
          clusterTime: Timestamp { low: 2, high: 1684847514, unsigned: true },
          signature: { hash: [Binary], keyId: [Long] }
        }
      },
      'ac-0qzaeb7-shard-00-01.nxgkbuq.mongodb.net:27017' => ServerDescription {
        address: 'ac-0qzaeb7-shard-00-01.nxgkbuq.mongodb.net:27017',
        type: 'RSSecondary',
        hosts: [
          'ac-0qzaeb7-shard-00-00.nxgkbuq.mongodb.net:27017',
          'ac-0qzaeb7-shard-00-01.nxgkbuq.mongodb.net:27017',
          'ac-0qzaeb7-shard-00-02.nxgkbuq.mongodb.net:27017'
        ],
        passives: [],
        arbiters: [],
        tags: {
          provider: 'AWS',
          workloadType: 'OPERATIONAL',
          region: 'ME_SOUTH_1',
          nodeType: 'ELECTABLE'
        },
        minWireVersion: 0,
        maxWireVersion: 17,
        roundTripTime: 322.56000000000006,
        lastUpdateTime: 183346518,
        lastWriteDate: 2023-05-23T13:11:54.000Z,
        error: null,
        topologyVersion: {
          processId: ObjectId { [Symbol(id)]: [Buffer [Uint8Array]] },
          counter: 11
        },
        setName: 'atlas-yyc43k-shard-0',
        setVersion: 2,
        electionId: null,
        logicalSessionTimeoutMinutes: 30,
        primary: 'ac-0qzaeb7-shard-00-02.nxgkbuq.mongodb.net:27017',
        me: 'ac-0qzaeb7-shard-00-01.nxgkbuq.mongodb.net:27017',
        '$clusterTime': {
          clusterTime: Timestamp { low: 2, high: 1684847514, unsigned: true },
          signature: { hash: [Binary], keyId: [Long] }
        }
      }
    },
    stale: false,
    compatible: true,
    heartbeatFrequencyMS: 10000,
    localThresholdMS: 15,
    setName: 'atlas-yyc43k-shard-0',
    maxElectionId: null,
    maxSetVersion: null,
    commonWireVersion: 0,
    logicalSessionTimeoutMinutes: 30
  },
  code: undefined
}

Node.js v18.12.0

解决思路

1. 排查网络层面问题

  • 本地网络可能存在防火墙或代理限制,导致无法持续连接MongoDB Atlas的主节点(报错显示主节点ac-0qzaeb7-shard-00-02.nxgkbuq.mongodb.net连接超时)。尝试关闭本地防火墙或切换网络(比如用手机热点)测试。
  • 检查本地是否能ping通15.185.70.41,或者用telnet测试27017端口是否能连通:telnet 15.185.70.41 27017,如果不通,说明网络层面存在阻断。

2. 修正代码中的错误

  • db.js里的SIGINT处理函数中,connection变量未定义,应该改为mongoose.connection,否则会导致未捕获的引用错误,可能间接影响连接稳定性:
    process.on("SIGINT", (err) => {
      if (err) {
        console.error(err);
      }
      mongoose.connection.close(() => { // 修正为mongoose.connection
        console.log("MongoDB connection closed due to app termination");
        process.exit(0);
      });
    });
    
  • disconnected事件的处理逻辑有问题:该事件触发时不一定会传入error参数,当前代码在无错误时会打印undefined并直接退出进程,这会导致正常的连接断开(比如心跳检测暂时失败)直接终止程序。建议调整逻辑,不要在无错误时直接退出,而是尝试重连:
    mongoose.connection.on("disconnected", () => {
      console.log("MongoDB connection disconnected, attempting to reconnect...");
      mongoose.connect(dbURI, {
        useNewUrlParser: true,
        useUnifiedTopology: true,
      });
    });
    

3. 优化Mongoose连接配置

  • 针对副本集连接,添加retryWrites: true和w: 'majority'配置,提升连接稳定性:
    mongoose.connect(dbURI, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      retryWrites: true,
      w: 'majority'
    });
    
  • 可以增加连接超时和心跳间隔的配置,适配本地网络情况:
    mongoose.connect(dbURI, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      serverSelectionTimeoutMS: 5000, // 服务器选择超时时间
      heartbeatFrequencyMS: 30000 // 心跳间隔,减少频繁检测
    });
    

4. 检查MongoDB Atlas配置

  • 确认Atlas的副本集状态正常,主节点是否在线。可以登录Atlas控制台查看集群状态,确认主节点没有故障。
  • 重新生成MongoDB连接字符串,确保没有包含错误的参数,比如是否正确选择了Node.js驱动版本,连接字符串中的用户名、密码是否正确。

内容的提问来源于stack exchange,提问作者liorlsa9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 06:19:55