Heroku部署Node.js后端遇H12请求超时问题求助
嘿,我之前也折腾过Heroku上的Telegram机器人,碰到过一模一样的H12超时问题,给你几个实用的排查和解决方向:
Heroku的H12错误就是请求超过30秒没收到响应,哪怕你没操作时也报错,大概率是机器人和Telegram的Webhook连接逻辑有问题,或者Heroku的dyno资源/休眠机制在搞鬼。
1. 先把Telegram Webhook的响应逻辑改对
Telegram对Webhook的要求特别严格:必须在5秒内返回200响应,不管你的任务有没有处理完。很多人踩坑就是把耗时操作(比如调用第三方API、复杂计算)直接放在Webhook的回调函数里,导致请求挂着超时——哪怕是发个"Hello world",如果异步逻辑没处理好,也会触发H12。
解决办法:
- 把所有耗时操作丢到后台队列里(比如用
bull、agenda这类Node.js队列库) - Webhook回调函数里啥也别干,直接返回空的200响应:
app.post('/webhook', (req, res) => { // 把请求内容丢到队列,后台处理 queue.add(req.body); // 立刻返回200,给Telegram一个交代 res.sendStatus(200); }); - 后台任务处理完之后,再主动调用Telegram的API给用户发消息,不要等着Webhook的请求来返回结果。
2. 解决Heroku Dyno的休眠问题
Heroku的免费/hobby级dyno如果30分钟没收到外部请求,就会自动休眠。唤醒的时候需要几秒时间,这时候如果Telegram刚好发请求过来,就会直接触发H12超时——哪怕你没操作,Telegram也会定期ping你的Webhook,刚好撞上休眠就会报错。
解决办法:
- 搞个定时任务,每隔25分钟给你的Heroku app发一个HTTP请求,保持dyno醒着。比如写个简单的Node.js脚本,或者用UptimeRobot这类免费工具,定时访问你的
/health接口(自己写个返回200的接口就行)。 - 代码里加个健康检查接口:
app.get('/health', (req, res) => { res.sendStatus(200); });
3. 排查第三方API的延迟问题
你说机器人要和若干API通信,如果这些第三方API响应慢,会直接拖垮你的后端。哪怕你没操作,要是代码里有定时轮询API的逻辑,也可能导致请求挂着超时。
解决办法:
- 给所有第三方API调用加超时限制,比如用
axios的话,设置timeout: 5000(5秒),超时就直接捕获错误,别让请求一直挂着:const axios = require('axios'); try { const response = await axios.get('https://third-party-api.com', { timeout: 5000 }); } catch (err) { console.error('API请求超时:', err); // 这里可以给用户发个"暂时无法处理,请稍后再试"的消息 } - 对频繁调用的API结果做缓存,比如用
redis(Heroku有免费的Redis插件),减少重复请求。
4. 扒Heroku日志找具体问题
别光盯着H12错误提示,去看Heroku的实时日志,能找到超时请求的具体路径和原因:
heroku logs --tail
看看哪些请求超时了,对应的代码是哪一段——比如是不是某个路由里有死循环,或者异步操作没加await导致响应一直没返回?
5. 调整Dyno资源配置
如果是免费dyno内存不够(比如代码有内存泄漏,或者处理的请求太多),也会导致响应变慢。可以试试:
- 升级到标准级dyno(如果预算允许)
- 代码里优化内存使用,比如及时释放不需要的变量,避免全局变量堆积过多数据。
内容的提问来源于stack exchange,提问作者Eu Román

