【问题标题】:Why is my Node API working locally, but not on Heroku?为什么我的 Node API 可以在本地工作,但不能在 Heroku 上工作?
【发布时间】:2021-04-26 00:03:44
【问题描述】:

问题

我已经为 Heroku 部署了一个 Node.js/Express.js/Mongoose API,但是当我点击端点时,我得到一个 503 状态代码并且 Heroku 提示告诉我有一个应用程序错误。

尝试解决方案

我在另一篇 Stackoverflow 帖子中读到,您需要在 Heroku 应用程序的设置中添加 MONGODB_URI 作为配置变量,因此我添加了连接字符串并将 MongoDB 连接更改为:

// Connect to DB
mongoose.connect(process.env.MONGODB_URI || uri, {useNewUrlParser: true, useUnifiedTopology: true}, () => 
    console.log('Connected to DB!')
);

但这似乎没有帮助。我还尝试将 &ssl=true 附加到连接字符串,但没有成功。然后我尝试将 Mongoose 版本更改为 5.7.0 并将 MongoDB 连接字符串更改为 Node 版本 2.12.12 或更高版本(来自 Atlas Cloud)。一个都没用。

应用的文件结构

这是我的 API 的非常简单的结构

在 index.js 中,我设置了 express 应用程序、设置路由、连接到端口并使用 Mongoose 连接到数据库:

const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
const uri = "mongodb+srv://username:password@devcluster.hesav.mongodb.net/quizappdb?retryWrites=true&w=majority";

const app = express();

// Middleware
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cors());

// Import routes
const questionRoutes = require('./routes/questions.js');
app.use('/question', questionRoutes);

// Set to port 5000 and listen on port
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`));

// Connect to DB
mongoose.connect(process.env.MONGODB_URI || uri, {useNewUrlParser: true, useUnifiedTopology: true}, () => 
    console.log('Connected to DB!')
);

(在 uri 中编辑的用户名和密码)

在 routes/questions.js 中,我使用 express 路由器定义 API 函数:

const express = require('express');
const router = express.Router();
const Question = require('../models/question');

// Get all questions
router.get('/', async (req, res) => {
    try {
        const questions = await Question.find();
        res.json(questions);

    } catch(err) {
        res.json({message: err})
    }
});


// Get questions by category
router.get('/:category', async (req, res) => {
    const category = req.params.category;
    console.log(category);
    Question.find({category: category})
    .exec()
    .then(doc => {
        console.log("From database", doc);
        if (doc) {
            res.status(200).json(doc);
        } else {
            res.status(404).json({message: 'No valid entry'})
        }
    })
    .catch(err => {
        console.log(err);
        res.status(500).json({
            error: err
        });
    })
})

// Add question
router.post('/', async (req, res) => {
    const question = new Question({
        category: req.body.category,
        description: req.body.description,
        option1: req.body.option1,
        option2: req.body.option2,
        option3: req.body.option3,
        option4: req.body.option4,
        answer: req.body.answer,
        
    });

    try {
        const savedQuestion = await question.save()
        res.json(savedQuestion);
    } catch(err){
        res.json({message: err})
    }
});

// Delete question by id
router.delete('/:questionId', async (req, res) => {
    try {
        const removedQuestion = await Question.remove({_id: req.params.questionId})
        res.json(removedQuestion);
    } catch(err) {
        res.json({message: err})
    }
})



module.exports = router;

为了让 Heroku 知道我使用的是哪个版本的 Node,我在 package.json 的“引擎”部分定义了它:

  "engines": {
    "node": "14.x"
  }

在我的 Procfile 中:

网络:节点 index.js

当我在 /question 访问应用程序时,它会挂起 30 秒,显示应用程序错误的 Heroku 提示,并且在我看到的日志中:

2021-01-21T16:56:32.313123+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/question" host=quiz-app-dk. herokuapp.com request_id=cda581cb-25c0-4980-a669-e65008a59ecd fwd="212.10.104.241" dyno=web.1 connect=1ms service=30001ms status=503 bytes=0 protocol=https

所以是 503 状态码。

当我指定一个类别并转到 /question/Sport 时,我得到相同的结果:

2021-01-21T16:57:10.687786+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/question/Sport" host=quiz-app- dk.herokuapp.com request_id=2620dc48-7581-406c-aa66-2085ee6decb3 fwd="212.10.104.241" dyno=web.1 connect=1ms service=30000ms status=503 bytes=0 protocol=https

与数据库的连接

还值得注意的是,与数据库的连接似乎发生了,正如我在 Heroku 日志中看到的那样:

2021-01-21T14:07:55.273864+00:00 app[web.1]:已连接到数据库!

但是,当我在本地执行其中任何一项操作时,一切正常。我怀疑路线有问题,但我不知道是什么。任何帮助是极大的赞赏。谢谢。

更新

我将数据库连接包装在 try catch 中并得到以下结果:

2021-01-21T17:07:08.861455+00:00 app[web.1]:无法连接到服务器。请启动服务器。错误:MongoNetworkError:第一次连接时无法连接到服务器 [devcluster-shard-00-00.hesav.mongodb.net:27017] [MongoNetworkError:连接 5 到 devcluster-shard-00-00.hesav.mongodb.net:27017关闭 2021-01-21T17:07:08.861463+00:00 app[web.1]:在 TLSSocket。

【问题讨论】:

  • 试试:app.enable('trust proxy')。更多信息here
  • @CarloCorradini 没用,但感谢您抽出宝贵时间尝试和帮助。
  • 不应该是/question/sport而不是/sport吗?
  • @L.Meyer 你是对的。不,我收到“MongooseError:操作questions.find() 缓冲在 10000 毫秒后超时”
  • 你能提供你的 Mongo 服务器和你使用的 mongoose 的版本吗?

标签: node.js express heroku mongoose


【解决方案1】:

解决方案

终于想通了。问题是 IP 没有被列入白名单,所以我无法连接到数据库。我需要做的是转到 MongoDB Cloud 上的网络访问并点击“添加 IP 地址”并单击“允许从任何地方访问”。在此之后,它按预期工作。感谢 L.Meyer 提供的所有帮助。

【讨论】:

    【解决方案2】:

    您应该在您的 mongodb 帐户中添加 IP 地址。只需进入 mongodb 集群,然后点击网络访问并添加此 ip 0.0.0.0/0

    【讨论】:

    • 您提交此内容时,我正在输入自己的答案,但您完全正确。我通过“允许从任何地方访问”来做到这一点,但那是一回事。感谢您的帮助。
    猜你喜欢
    • 2021-05-10
    • 2012-06-18
    • 2023-03-10
    • 2023-03-03
    • 2012-04-01
    • 2017-08-14
    • 1970-01-01
    • 1970-01-01
    • 2021-01-14
    相关资源
    最近更新 更多