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

如何在Express中间件中判断MongoDB集群是否存在主节点且可写入?

判断MongoDB集群主节点状态及可写性的方法

Great question! Let's tackle both parts of your problem step by step—first checking for a primary node in the cluster, then detecting read-only mode when connected with connectWithNoPrimary: true in your Express middleware.

1. 客户端判断MongoDB集群是否存在主节点

不管你用原生MongoDB驱动还是Mongoose,都可以通过isMaster管理命令获取集群状态详情。这个命令会返回当前连接节点及整个集群的元数据信息。

在Mongoose中,你可以从已建立的连接中获取底层的管理数据库,然后执行这个命令:

async function clusterHasPrimary() {
  try {
    const adminDb = mongoose.connection.db.admin();
    const clusterStatus = await adminDb.command({ isMaster: 1 });
    
    // 两个判断逻辑:
    // - `ismaster`:当前连接的节点是主节点时为true
    // - `primary`:集群存在主节点时会返回该字段(即使我们连接的是从节点)
    return clusterStatus.ismaster || !!clusterStatus.primary;
  } catch (err) {
    console.error('检查主节点状态出错:', err);
    return false;
  }
}

这个函数会返回true,只要集群存在主节点(不管客户端直接连接的是主节点还是从节点)。

2. 在Express中间件中判断是否处于只读状态(无主节点时)

你说得对,mongoose.connection.readyState只能告诉你连接是否已建立,无法直接判断是否允许写操作。当使用connectWithNoPrimary: true时,即使集群没有主节点,连接状态也会显示为就绪(readyState = 1),但所有写操作都会失败。

要在中间件中提前检测这种只读状态,我们可以复用isMaster命令来判断集群是否支持写操作:

async function checkWritableConnection(req, res, next) {
  try {
    const adminDb = mongoose.connection.db.admin();
    const clusterStatus = await adminDb.command({ isMaster: 1 });

    // 集群可写的条件:
    // - 当前直接连接到主节点(`ismaster: true`)
    // 或者
    // - 集群存在主节点,且当前连接的不是只读从节点
    const isWritable = clusterStatus.ismaster || (!!clusterStatus.primary && !clusterStatus.secondary);

    if (!isWritable) {
      return res.status(503).json({ 
        error: '集群处于只读模式,无法执行写操作。' 
      });
    }

    next();
  } catch (err) {
    console.error('检查可写状态出错:', err);
    return res.status(500).json({ error: '集群状态验证失败' });
  }
}

// 在需要写权限的路由上使用这个中间件
app.post('/api/records', checkWritableConnection, async (req, res) => {
  // 这里写你的写操作逻辑(比如创建文档)
});

优化提示

如果担心每次写请求都执行isMaster命令带来性能开销,可以缓存结果(比如将可写状态存在变量中,每隔5-10秒用setInterval刷新一次),这样能平衡状态新鲜度和性能。

另外需要注意:当连接到没有主节点的集群(且connectWithNoPrimary: true)时,isMaster的返回结果会是ismaster: false、没有primary字段,且secondary: true(如果连接的是从节点)——这些都是写操作被禁用的标志。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:24:46