Heroku部署Node.js应用成功 访问报H10崩溃错误
Heroku返回H10应用崩溃错误的直接诱因是MongoDB连接建立失败触发未捕获异常,导致Node进程直接退出,从错误栈可以明确是connect-mongodb-session初始化会话存储时的连接被服务端主动断开,和npm脚本、Node版本本身没有关系,按以下优先级排查即可解决:
第一优先级:修复MongoDB Atlas网络白名单配置
这是该场景下90%以上故障的诱因。Heroku dyno的出口IP是动态变化的,如果你在MongoDB Atlas后台的IP白名单里只添加了本地开发环境的固定IP,Heroku的服务器发起连接时会直接被Atlas防火墙拦截,表现就是TCP连接建立后立刻被关闭。
直接登录Atlas控制台,进入Network Access配置页,添加0.0.0.0/0到白名单(允许所有IP访问,Atlas本身有账号密码鉴权,配合数据库账号最小权限配置不会有安全风险,适配PaaS平台动态IP的场景),等待1-2分钟配置生效后重试即可。第二优先级:修复
connect-mongodb-session的连接配置
从现有代码看,你只给mongoose传入了MongoDB连接串,会话存储的连接逻辑是在./middleware/middleware文件中独立初始化的,大概率存在两个问题:一是会话存储单独创建了新的数据库连接,没有和mongoose共用连接逻辑,二是初始化时没有监听连接错误,异常直接抛出打崩进程。
修改会话存储初始化代码如下,和mongoose复用同一份连接配置,同时增加错误监听:const session = require('express-session'); const MongoDBStore = require('connect-mongodb-session')(session); // 注意:这里的MONGODB_URI和mongoose连接用同一个变量,不要单独硬编码连接串 const store = new MongoDBStore({ uri: MONGODB_URI, collection: 'sessions', connection: mongoose.connection // 复用mongoose已建立的连接,避免重复建连 }); // 必须加错误监听,避免连接异常直接触发未捕获错误崩进程 store.on('error', err => { console.error('Session storage connection failed:', err); });另外你当前的MongoDB连接串没有指定具体的数据库名,拼接完成的串默认会连到test库,容易触发权限校验失败,在连接串的集群域名后加上自定义的数据库名即可,格式参考:
mongodb+srv://账号:密码@blogapp.ool50gr.mongodb.net/blogDB?retryWrites=true&w=majority第三优先级:修复线上环境配置读取失效问题
你当前用config包读取数据库账号密码,这类配置文件通常会被.gitignore排除在代码提交之外,Heroku部署时拉取不到本地的配置文件,会直接读不到db-admin和db-password的值,拼出来的连接串是无效的。
不要把敏感配置存在代码仓库里,直接用Heroku自带的配置变量存储:- 本地执行Heroku CLI命令写入配置:
heroku config:set DB_ADMIN=你的数据库账号 DB_PASSWORD=你的数据库密码 - 修改代码里的连接串拼接逻辑,优先读环境变量:
const dbAdmin = process.env.DB_ADMIN || config.get('db-admin'); const dbPwd = process.env.DB_PASSWORD || config.get('db-password'); const MONGODB_URI = `mongodb+srv://${dbAdmin}:${dbPwd}@blogapp.ool50gr.mongodb.net/blogDB?retryWrites=true&w=majority`;
- 本地执行Heroku CLI命令写入配置:
第四优先级:校验依赖版本兼容性
你当前使用的mongoose 6.x版本内置的是4.x版本的MongoDB Node驱动,如果connect-mongodb-session版本低于3.0,会存在驱动兼容问题,也会抛出连接被关闭的错误。本地执行npm install connect-mongodb-session@latest更新到兼容版本,提交更新后的package-lock.json重新部署即可。
额外提一句:把nodemon从dependencies依赖移到devDependencies,线上生产环境不需要这个热重载工具,避免不必要的资源消耗和潜在冲突。
重新部署时执行heroku logs --tail查看实时日志,看到控制台打印Database connected!和App is running on PORT XXXX的日志后,再访问应用地址就不会出现503和H10错误了。
内容的提问来源于stack exchange,提问作者Md Muaz Ahmed

