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

Vercel部署NodeJS项目访问MongoDB遇504 Gateway Timeout求助

问题:Node.js项目部署Vercel后MongoDB访问504超时

项目结构

/configs
  db.config.js
/routes
  testRoutes.js
index.js
vercel.json

核心代码

index.js

const express = require('express');
const connectToDb = require('./configs/db.config');
const cors = require('cors');
const path = require('path');
const testRouter = require('./routes/testRoutes');
const app = express();
const PORT = process.env.PORT || 5000;

app.use(cors());
app.use(express.json());
app.use('/', express.static(path.join(__dirname, '/public')));

app.use('/test', testRouter.getUsers);

connectToDb()
  .then((res) => {
    app.listen(PORT, () => {
      console.log(`Server is running on port: ${PORT}`);
    });
  })
  .catch((err) => {
    console.log(err);
  });

module.exports = app;

db.config.js

const {MongoClient} = require('mongodb');
const uri = `mongodb+srv://${process.env.DB_USER}:` +
            `${process.env.DB_PASSWORD}@${process.env.DB_CLUSTER_URL}/` +
            `?retryWrites=true&w=majority&appName=${process.env.DB_APP_NAME}`;
const client = new MongoClient(uri);

let database;

const connectToDb = async () => {
  if (database) {
    return database;
  }
  try {
    await client.connect();
    console.log('Connected to MongoDB');
    database = client.db(process.env.DB_NAME);
    return database;
  } catch (error) {
    console.log(error);
  }
};

module.exports = connectToDb;

testRoutes.js

const connectToDb = require('../configs/db.config');

const getUsers = async (req, res) => {
  try {
    let db = await connectToDb();
    const collection = db.collection(process.env.DB_COLLECTION);
    const data = await collection.find({}).toArray();
    res.send(data);
  } catch (error) {
    console.error('Error accessing the database', error);
    res.status(500).send('Failed to fetch data');
  }
};

module.exports = {
  getUsers,
};

vercel.json

{
  "version": 2,
  "builds": [{
      "src": "index.js",
      "use": "@vercel/node"
  }],
  "routes": [{
      "src": "/(.*)",
      "dest": "index.js"
  }]
}

问题现象

本地运行时访问http://localhost:5000/test可正常返回数据库记录,但部署到Vercel后访问该路由出现504 Gateway Timeout错误,Vercel日志无有效报错信息。

可能原因及解决方向

1. MongoDB网络访问权限未开放Vercel IP

MongoDB Atlas默认仅允许本地IP访问,Vercel服务器IP动态变化,需在MongoDB控制台调整权限:

  • 登录MongoDB Atlas控制台,进入目标集群
  • 左侧菜单选择Network Access,点击Add IP Address
  • 测试阶段可输入0.0.0.0/0(允许所有IP),生产环境建议添加Vercel官方公布的IP段

2. Vercel环境变量未正确配置

本地.env文件的数据库凭证不会自动同步到Vercel,需手动添加:

  • 登录Vercel控制台进入项目,选择Settings -> Environment Variables
  • 添加所有所需变量:DB_USER、DB_PASSWORD、DB_CLUSTER_URL、DB_APP_NAME、DB_NAME、DB_COLLECTION
  • 确保变量名、值与本地完全一致,无拼写错误

3. Vercel Serverless特性兼容问题

Vercel的Serverless Function不支持长期保持数据库连接,当前单例连接逻辑需调整:

  • 修改db.config.js,避免长期持有连接,每次请求重新建立或检查连接:
    const {MongoClient} = require('mongodb');
    
    const connectToDb = async () => {
      const uri = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_CLUSTER_URL}/?retryWrites=true&w=majority&appName=${process.env.DB_APP_NAME}`;
      const client = new MongoClient(uri);
      try {
        await client.connect();
        console.log('Connected to MongoDB');
        return client.db(process.env.DB_NAME);
      } catch (error) {
        console.log(error);
        await client.close();
        throw error;
      }
    };
    
    module.exports = connectToDb;
    
  • 移除index.js中的app.listen()调用,Vercel会自动处理请求,无需手动启动服务器

4. MongoDB连接超时配置过短

冷启动时Vercel建立连接可能耗时较长,可增加连接超时参数:

const client = new MongoClient(uri, {
  serverSelectionTimeoutMS: 5000,
  connectTimeoutMS: 5000
});

5. 增加日志排查

在getUsers函数中添加更详细的日志,方便定位问题:

const getUsers = async (req, res) => {
  try {
    console.log('Checking environment variables:', {
      DB_USER: !!process.env.DB_USER,
      DB_CLUSTER_URL: !!process.env.DB_CLUSTER_URL,
      DB_NAME: !!process.env.DB_NAME
    });
    let db = await connectToDb();
    console.log('Connected to database:', db.databaseName);
    const collection = db.collection(process.env.DB_COLLECTION);
    console.log('Accessing collection:', process.env.DB_COLLECTION);
    const data = await collection.find({}).toArray();
    console.log('Fetched data count:', data.length);
    res.send(data);
  } catch (error) {
    console.error('Full error details:', error);
    res.status(500).send('Failed to fetch data');
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 17:29:53