Node JS 正在运行但没有响应。工作,但随后定期停止响应

Posted

技术标签:

【中文标题】Node JS 正在运行但没有响应。工作,但随后定期停止响应【英文标题】:Node JS running but not responding. Works but then periodically stops responding 【发布时间】:2021-04-17 01:10:00 【问题描述】:

我创建了我的第一个 NodeJS Api(也是第一次使用 JS),因此遇到了一些问题,真的希望得到一些帮助/指导。

我当前的问题是 API 可以正常工作,但是它会时不时地(每天不止一次)停止响应。 (使用邮递员进行测试)。它不会以“无响应”来响应,它只是一直在尝试,好像在等待响应一样。

当我登录到我使用的节点时:

lsof -i tcp:3000
COMMAND   PID  USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
node    22361 [myserver] 18u  IPv6 190588033      0t0  TCP *:hbci (LISTEN)
kill -9 22361

当我杀死它时,我等待 10 秒然后它会再次启动,因为我已经安装了 FOREVER。

问题是节点似乎只是……没有运行。如果它崩溃了,它不会重新启动并再次工作,而是它只是“那里”。

我该如何诊断?

我也安装了 Nodemon,但由于出现 EAINUSE 错误,无法真正让它正常工作

我已经在我的 VPS 上创建了文件。

在我的 Win10 PC 上使用 Visual Stdio Code 进行 SSH。

看了几个 youtube 视频让我跑步

我的主js文件很基础:

js文件:

const app = require('./app');
const port = process.env.port || 3000;
app.listen(port);

目前我似乎无法找到“为什么”节点从工作并响应停滞、运行但实际上不工作!

乐于分享代码,js文件大概12个左右,不想在这扔太多。

包.json:


  "name": "qudaapi",
  "version": "1.0.0",
  "description": "NodeJSAPI",
  "main": "qudaserver.js",
  "scripts": 
    "start": "node qudaserver.js"
      ,
  "author": "GAngel",
  "license": "ISC",
  "dependencies":    
    "bcryptjs": "^2.4.3",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "jsonwebtoken": "^8.5.1",
    "morgan": "^1.10.0",
    "mysql": "^2.18.1"
  

App.js

const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');

const app = express();

app.use(morgan('dev'));
app.use(bodyParser.urlencoded(extended: false));
app.use(bodyParser.json());

app.use((req,res,next)=>
    res.header("Access-Control-Allow-Origin","*");
    res.header("Access-Control-Allow-Headers","Origin,X-Requested-With,Content-Type,Accept,Authorization");

    if (req.method === 'OPTIONS')
        res.header('Access-Control-Allow-Methods','PUT,POST,PATCH,DELETE,GET');
        return res.status(200).json();
    
    next();
);

//Import Routes
const chemistRoutes = require('./api/routes/chemists');
const smsHxRoutes = require('./api/routes/smsHx');
const authRoute = require('./api/routes/auth');
const webhookRoutes = require('./api/routes/stripehook');
const orderRoutes = require('./api/routes/orders');
const comboDataRoutes = require('./api/routes/comboData');
const staffRoutes = require('./api/routes/staff');
const orderListsRoutes = require('./api/routes/orderLists');
const contactLogRoutes = require('./api/routes/contactLog');
const licenseRoutes = require('./api/routes/license');

//Route Middleware
app.use('/smsHx',smsHxRoutes);
app.use('/chemists',chemistRoutes);
app.use('/register',authRoute);
app.use('/stripehook',webhookRoutes);
app.use('/orders',orderRoutes);
app.use('/comboData',comboDataRoutes);
app.use('/staff',staffRoutes);
app.use('/orderLists',orderListsRoutes);
app.use('/contactLog',contactLogRoutes);
app.use('/license',licenseRoutes);



app.use((req,res,next) => 
    const error = new Error('Endpoint not Found');
    error.status = 404;
    next(error);
)

app.use((error,req,res,next) => 
res.status(error.status || 500);
res.json(
    error: 
        message: error.message
    
    );

);


module.exports = app;

导致某种失败循环的部分:

//Login_Get APIkey
router.post('/login',verifyQUDA,async (req,res) => 
    let loginChemist = req.body;
    const realPass = loginChemist.chemistPassword;
    
    // CHECK Password  
   
    var sqlString = "SELECT * From tblChemists WHERE userName = ?;";

        connection.query(sqlString,[loginChemist.userName], async (err,rows,fields)=>
            if (rows && Array.isArray(rows) && rows.length) 

                    const savedHash = rows[0].chemistpass;
                    const chemistID = rows[0].chemistID;
                    const validPass = await bcrypt.compare(realPass,savedHash);
                    

                    if(!validPass)
                        return res.status(200).json(
                            Result: false
                                )
                    else

                        const token = jwt.sign(_id: chemistID,process.env.TOKEN_SECRET);
                        res.header('auth-token',token);
                        return res.status(200).json(
                            Result: true,
                            API_Token: token
                                )
                     

                   
            )
        
        
        

)

所以我的代码运行并且我可以使用 API,我似乎能够很好地使用它(所有路由)并获得预期的响应,但是如果我随机登录并进行测试,有时它会关闭并且邮递员一直在旋转等待响应,但是当我检查时……它仍在“运行”

真的很想知道我应该做些什么来诊断?

编辑: 上面的代码是有时会循环或导致问题的部分。 我发现 api 实际上正在运行,因为其他 API 调用正在运行,并且如果我不添加标头,这个 API 调用“有效”。 因此,如果没有标头,或者标头 API 密钥不正确,我可以获得响应 500。

问题似乎是标题是否正确,并且用户和密码是否正确有时我只是得到一个循环响应...... 但是,代码确实可以工作,并在这里和那里提供我需要的 API_Token,但有时只是像疯子一样循环!

【问题讨论】:

您只需要在服务器中记录内容,直到您可以缩小卡住的范围。例如,当一个传入请求被卡住时,它会到达第一个中间件吗?或者它甚至没有那么远?我要寻找的东西是:1)泄漏数据库连接或数据库资源,2)泄漏文件句柄,3)没有完整错误处理并且有一些路径在出现错误时无法发送任何响应的路由, 4) 一些中间件有一个条件,它可以进入它从不调用next() 或发送响应(从而挂起请求)。 在您显示的一个路由处理程序中,您似乎在发送响应后没有退出的循环内调用res.status(200).json()。如果您可以在循环中多次进入此if 语句,这是错误的。每个请求都会得到一个响应,而不是 N 个响应。这本身可能不会导致您的症状,但这是错误的,需要修复。 谢谢大家,我会马上研究一下,看看我能拼出什么 你是在生产环境中运行这个吗? 您添加的代码有许多不返回任何响应的代码路径。而且,它缺少一堆错误处理,这也会导致没有响应被发送。 【参考方案1】:

您的/login 处理程序有许多代码路径,它们不发送任何响应并且缺少一些错误处理,因此您最终可能会出现“静默”错误和挂起的请求。就个人而言,我会在你的数据库上切换到 promise API,但在不进行结构更改的情况下,这是至少确保你始终发送响应并捕获错误的一种方法:

//Login_Get APIkey
router.post('/login', verifyQUDA, (req, res) => 
    const loginChemist = req.body;
    // CHECK Password
    var sqlString = "SELECT * From tblChemists WHERE userName = ?;";
    connection.query(sqlString, [loginChemist.userName], async (err, rows, fields) => 
        try 
            if (err) 
                // catch database errors
                console.log(err);
                res.sendStatus(500);
             else if (rows && rows.length) 
                const savedHash = rows[0].chemistpass;
                const chemistID = rows[0].chemistID;
                const realPass = loginChemist.chemistPassword;
                const validPass = await bcrypt.compare(realPass, savedHash);
                if (!validPass) 
                    res.status(200).json( Result: false );
                 else 
                    const token = jwt.sign( _id: chemistID , process.env.TOKEN_SECRET);
                    res.header('auth-token', token);
                    res.status(200).json( Result: true, API_Token: token );
                

             else 
                // send some status here when the username does not exist
                // or your rows condition is not met
                res.sendStatus(404);
            
         catch (e) 
            // this catches any exception in this scope or await rejection
            console.log(e);
            res.sendStatus(500);
        
    );
);

【讨论】:

非常感谢@jfriend00 我已经使用了该代码并且运行良好。我发现 (&& Array.isArray) 部分是不需要的,我认为这也导致了问题,所以我将其删除。我将对我的其他 API 部分使用这种设计/处理来清理它们。再次感谢您花时间帮助我 好的,这有助于缩小问题范围,但它仍然“损坏”API 正在处理除此之外的所有调用,它重新发送了内部服务器错误 500 响应。考虑到其余的 api 都在工作,我怎么知道这里出了什么问题? @GlennAngel - 好吧,我建议的代码在任何地方都会发送错误 500 响应,它还会记录错误的详细信息,所以我建议查看该日志记录,看看你是否能找出原因到了那里。您还可以添加更多日志记录来检查所有内容并尝试找出问题所在。 @GlennAngel - 此代码主要通过三种方式生成 500 错误。首先,数据库给你一个错误。其次,您在处理行数据时抛出了异常。三、await bcrypt.compare()被拒。 好的,谢谢,所以我的最后一个问题(菜鸟)是,如果我进入我的 cmd 屏幕并启动节点,我可以在打印时看到控制台,但是如果我关闭我的 cmd 和节点正在运行..我如何访问该日志?

以上是关于Node JS 正在运行但没有响应。工作,但随后定期停止响应的主要内容,如果未能解决你的问题,请参考以下文章

使用 Electron 编译 node.js 版本时出现问题

通过套接字发送命令,但每次都等待响应(Node.js)

Nodejs(express)正在运行但请求不起作用

Node.js + Mongoose 可以在本地工作,但不能在 Heroku 上工作

Node.js 和 Socket.IO 在某些服务器中没有响应

Node.js:Jest + redis.quit() 但打开句柄警告仍然存在