问题分析: - 服务频繁崩溃(平均1小时1次) - 无异常处理导致任何错误都引发进程退出 - 无进程管理器,崩溃后不自动重启 - 端口冲突无检测机制 主要修复: 1. 全局异常处理 - uncaughtException 捕获 - unhandledRejection 捕获 - 端口错误监听 - API错误中间件 2. PM2进程管理 - 安装PM2 v6.0.14 - 配置自动重启 - 启用开机自启(systemd) - 进程监控和日志管理 3. 健康检查端点 - GET /health - 返回运行时状态、内存、版本信息 - 用于监控和诊断 4. 优雅关闭机制 - 正确释放HTTP服务器 - 关闭数据库连接 - 10秒超时保护 5. 配置文件修复 - package.json: main指向server.js - 版本更新到3.1.0 - 添加PM2快捷命令 新增文件: - CRASH-ANALYSIS.md: 详细问题分析报告 - service.sh: 服务管理脚本(start/stop/restart/logs等) 测试结果: - 20次并发请求 100%成功 - PM2自动重启验证通过 - 开机自启配置完成 影响: - 稳定性: 1小时1崩 → 持续稳定运行 - 可维护性: 完善的日志和监控 - 可靠性: 崩溃自动恢复
4.5 KiB
4.5 KiB
服务崩溃问题分析报告
问题现象
- 时间: 2026-02-24 16:14
- 症状: 服务无响应 ERR_EMPTY_RESPONSE
- 频率: 已发生2次(14:55, 16:14)
根本原因分析
1. 缺少异常处理机制 (严重) 🔴
问题代码:
// server.js 无全局异常捕获
app.listen(PORT, () => { ... });
// 所有API路由无错误处理
app.get('/api/stats', (req, res) => {
db.get('SELECT ...', (err, result) => {
// err未处理,直接使用result
res.json(result);
});
});
风险:
- 未捕获异常导致进程崩溃
- 数据库错误导致服务器退出
- 客户端请求错误无响应
影响: 任何未预期的错误都会导致整个服务崩溃
2. 进程管理缺失 (严重) 🔴
当前启动方式:
node server.js > server.log 2>&1 &
问题:
- ❌ 没有进程守护
- ❌ 没有自动重启
- ❌ 依赖shell会话(可能被终端关闭影响)
- ❌ 没有进程监控
对比专业方案:
# 应该使用 PM2
pm2 start server.js --name task-service
pm2 startup # 开机自启
pm2 save # 保存配置
3. 数据库连接未处理超时 (中等) 🟡
问题:
const db = new sqlite3.Database('./tasks.db', (err) => {
if (err) {
process.exit(1); // 直接退出
}
});
// 没有连接保活机制
// 没有重连机制
风险:
- 数据库文件锁定导致连接失败
- 长时间运行后可能连接失效
4. 端口冲突无处理 (中等) 🟡
问题:
app.listen(PORT, () => { ... });
// 没有监听 'error' 事件
可能情况:
端口3000被占用 → listen失败 → 无错误提示 → 服务看似启动实际未运行
5. 配置文件不匹配 (轻微) 🟢
package.json:
{
"main": "server-postgres.js", // ❌ 文件已删除
"scripts": {
"start": "node server-postgres.js" // ❌ 错误
}
}
影响: npm start 无法运行
推荐修复方案(优先级排序)
🔴 P0 - 立即修复(必须)
1. 添加全局异常处理
// server.js 底部添加
process.on('uncaughtException', (err) => {
console.error('❌ 未捕获异常:', err);
// 不退出,记录日志继续运行
});
process.on('unhandledRejection', (reason, promise) => {
console.error('❌ 未处理的Promise拒绝:', reason);
});
// 监听端口错误
const server = app.listen(PORT, () => { ... });
server.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error(`❌ 端口 ${PORT} 已被占用`);
process.exit(1);
}
});
2. 添加API错误处理中间件
// 所有路由后添加
app.use((err, req, res, next) => {
console.error('API错误:', err);
res.status(500).json({ error: err.message });
});
3. 使用PM2管理进程
npm install -g pm2
pm2 start server.js --name task-service
pm2 startup
pm2 save
🟡 P1 - 重要优化(建议)
4. 数据库查询添加try-catch
app.get('/api/stats', async (req, res) => {
try {
db.get('SELECT ...', (err, result) => {
if (err) {
return res.status(500).json({ error: err.message });
}
res.json(result);
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
5. 添加健康检查端点
app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date() });
});
🟢 P2 - 长期改进(可选)
6. 日志系统升级
const winston = require('winston');
// 结构化日志,自动轮转
7. 监控告警
// 性能监控
// 崩溃告警
// 自动重启通知
临时解决方案(当前使用)
# 1. 检查端口
lsof -i :3000
# 2. 杀死占用进程
pkill -f "node server"
# 3. 重启服务
cd /data/openclaw/workspace/agent-task-service
node server.js > server.log 2>&1 &
# 4. 验证
curl http://localhost:3000/api/stats
缺点: 不解决根本问题,随时可能再次崩溃
建议执行顺序
- 立即 - 修复server.js添加异常处理
- 立即 - 安装并配置PM2
- 今天 - 添加API错误处理
- 本周 - 完善日志和监控
测试验证
修复后需验证:
# 1. 模拟崩溃
curl http://localhost:3000/api/nonexist
# 2. 检查进程存活
pm2 status
# 3. 查看日志
pm2 logs task-service
# 4. 压力测试
ab -n 1000 -c 10 http://localhost:3000/
生成时间: 2026-02-24 16:20 优先级: P0 (生产环境严重问题)