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

Node.js错误追踪方法及服务异常不宕机实现方案咨询

解决Node.js服务器错误追踪与防崩溃问题

Hey there! 刚部署的Node.js应用突然因为包报错宕机确实头疼,我来给你梳理下具体的解决步骤,分错误追踪和防宕机两部分来说:

一、全面追踪错误的方法

1. 捕获全局未处理的异常与Promise拒绝

Node.js默认会因为未捕获的uncaughtException或unhandledRejection直接崩溃,你可以先给进程绑定监听事件,把错误信息完整记录下来:

// 在应用入口文件顶部添加
const fs = require('fs');
const logError = (err, type) => {
  const errorLog = `[${new Date().toISOString()}] ${type}: ${err.stack}\n`;
  fs.appendFileSync('./error.log', errorLog, 'utf8');
  console.error(err);
};

process.on('uncaughtException', (err) => {
  logError(err, 'Uncaught Exception');
  // 注意:uncaughtException后进程状态不稳定,建议后续交由进程管理器自动重启
});

process.on('unhandledRejection', (reason, promise) => {
  logError(reason, 'Unhandled Rejection');
  console.log('关联Promise:', promise);
});

2. 使用专业日志库增强追踪能力

原生日志功能有限,推荐用winston或pino这类库来做分级日志(info/warn/error),还能自动按日期分割日志,方便后期回溯排查:
比如winston的基础配置:

const winston = require('winston');

const logger = winston.createLogger({
  level: 'error',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

// 开发环境输出到控制台方便调试
if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.simple()
  }));
}

// 之后用logger.error(err)统一记录错误

3. 定位具体包的错误

从错误栈信息里找到报错的包路径(比如node_modules/xxx/package/file.js),可以:

  • 查看该包的版本,尝试更新到最新稳定版(执行npm update <package-name>)
  • 去该包的代码仓库issues里搜类似错误,看有没有官方解决方案或社区补丁
  • 临时替换为功能相似的其他包测试,确认是否是该包本身的问题

4. 借助进程管理器查看日志

如果用PM2管理进程,直接执行pm2 logs就能查看实时的应用日志,pm2 show <你的应用名>可以看到崩溃次数、重启记录等详细信息,PM2会自动保存崩溃日志到本地目录,方便后期分析。

二、实现服务器遇错不宕机的方案

1. 用进程管理器自动重启

最省心的方式是用PM2这类进程管理器,它会在进程崩溃时自动重启,还能监控CPU、内存资源使用:

# 全局安装PM2
npm install pm2 -g
# 启动应用并命名
pm2 start app.js --name my-node-app
# 设置开机自启
pm2 startup
pm2 save

2. 框架级全局错误处理(Express/Koa为例)

如果你用Express,一定要加全局错误中间件,捕获路由里的所有错误,避免单个请求的错误导致整个服务器崩溃:

// Express 全局错误中间件(要放在所有路由定义之后)
app.use((err, req, res, next) => {
  logger.error(err.stack);
  res.status(500).json({ message: '服务器内部错误' });
});

Koa的话可以用try/catch包裹中间件逻辑,或者使用专门的错误处理中间件来捕获异常。

3. 规范Promise与async/await的错误处理

所有Promise必须加.catch(),用async/await时一定要包在try/catch里,避免未处理的Promise拒绝导致进程崩溃:

// 错误示例:未处理Promise拒绝
// fetchData().then(data => console.log(data));

// 正确做法
fetchData()
  .then(data => console.log(data))
  .catch(err => logger.error('Fetch data error:', err));

// async/await的正确写法
async function handleRequest() {
  try {
    const data = await fetchData();
    console.log(data);
  } catch (err) {
    logger.error('Handle request error:', err);
  }
}

4. 隔离易出错的第三方包

如果某个第三方包频繁崩溃,可以把调用它的逻辑放在子进程里,子进程崩溃不会影响主进程,还能单独重启子进程:

const { fork } = require('child_process');

// 子进程文件:child.js
// process.on('message', async (task) => {
//   try {
//     // 调用易出错的包逻辑
//     const result = await riskyPackageFunction(task);
//     process.send({ success: true, result });
//   } catch (err) {
//     process.send({ success: false, error: err.stack });
//   }
// });

const child = fork('./child.js');
child.on('message', (response) => {
  if (response.success) {
    console.log('子进程返回结果:', response.result);
  } else {
    logger.error('子进程执行出错:', response.error);
    // 重启子进程
    child.kill();
    // 重新创建子进程
  }
});

这样一套组合拳下来,既能完整追踪所有错误,又能保证服务器不会因为单个错误直接宕机啦。

内容的提问来源于stack exchange,提问作者Mr.Smith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 20:17:30