使用whatsapp-web.js的NestJS应用运行数天后崩溃且停止接收请求
使用whatsapp-web.js的NestJS应用运行数天后崩溃且停止接收请求
Hey there, sorry to hear about this tricky silent crash issue—those are always the most frustrating to debug! Let’s walk through some common culprits and fixes tailored to your stack:
1. 排查内存泄漏(whatsapp-web.js的高频问题)
whatsapp-web.js基于Puppeteer,长时间运行很容易积累内存占用,最终导致服务无响应:
- 清理未移除的事件监听器:检查你的
WhatsAppClientsManager,如果给客户端绑定了message、ready这类事件,一定要在客户端断开/销毁时移除对应的监听器。比如:// 绑定监听器时保存引用 const messageHandler = (msg) => { /* 处理逻辑 */ }; client.on('message', messageHandler); // 客户端销毁前移除 client.on('disconnected', () => { client.off('message', messageHandler); }); - 限制Puppeteer内存使用:初始化whatsapp-web.js的
Client时,给Puppeteer加内存限制参数,避免无节制占用资源:const client = new Client({ puppeteer: { args: [ '--no-sandbox', '--disable-dev-shm-usage', '--max-old-space-size=512', // 限制堆内存为512MB '--disable-gpu' ] } });
2. 确保NestJS服务生命周期管理正确
如果你的WhatsAppClientsManager是单例,一定要处理好客户端的销毁与重连:
- 实现生命周期钩子:在管理器中加入
OnModuleDestroy钩子,确保应用关闭时销毁客户端,避免残留进程:@Injectable() export class WhatsAppClientsManager implements OnModuleDestroy { private clients = new Map<string, Client>(); async onModuleDestroy() { for (const client of this.clients.values()) { await client.destroy().catch(err => console.error('Failed to destroy client:', err)); } } } - 监控客户端状态:定期检查客户端是否处于
ready状态,一旦断开自动触发重连逻辑,避免依赖失效导致服务卡住。
3. 捕获静默错误
很多时候错误被底层吃掉,没有输出到日志:
- 全局未捕获错误监听:在
bootstrap函数里添加全局错误捕获,把隐藏的错误打出来:async function bootstrap() { // ... 现有代码 process.on('uncaughtException', (err) => { console.error('[FATAL] Uncaught Exception:', err); }); process.on('unhandledRejection', (reason, promise) => { console.error('[WARN] Unhandled Rejection at:', promise, 'Reason:', reason); }); } - 客户端错误监听:给每个whatsapp客户端绑定
error事件,不要漏掉客户端层面的错误:client.on('error', (err) => { console.error('WhatsApp Client Error:', err); // 这里可以触发重连逻辑 await this.reconnectClient(clientId); });
4. 兜底:资源监控与自动重启
作为最后防线,用进程管理器监控资源,自动重启服务:
- 用PM2管理进程:创建PM2配置文件,设置内存阈值触发自动重启:
{ "name": "nest-whatsapp-app", "script": "dist/main.js", "max_memory_restart": "500M", // 内存超过500MB时重启 "log_file": "app.log", "error_file": "error.log" } - 内存自检重启:在应用里加定时任务,检查内存占用,超过阈值时优雅退出(配合PM2自动重启):
setInterval(() => { const { heapUsed } = process.memoryUsage(); if (heapUsed > 450 * 1024 * 1024) { // 450MB阈值 console.warn('Memory usage exceeded, initiating graceful restart'); process.exit(0); } }, 60000); // 每分钟检查一次
5. Cron任务适配
如果你的Cron依赖WhatsApp客户端,要在任务里先检查客户端状态:
@Cron('0 */6 * * *') // 每6小时执行一次 async handleCronTask() { try { const client = this.whatsAppManager.getClient('your-client-id'); if (!client || !client.isReady) { console.warn('WhatsApp client not ready, skipping cron task'); await this.whatsAppManager.reconnectClient('your-client-id'); return; } // 执行你的任务逻辑 } catch (err) { console.error('Cron task failed:', err); } }
建议先从捕获静默错误和检查内存泄漏入手,这些是这类问题最常见的根源。
备注:内容来源于stack exchange,提问作者Hossein Babamoradi
相关产品推荐
相关产品推荐

