nodejs 4.x 的项目, 须要升级到6.9.5(当时最新的稳定版本)以改善性能和可靠性.前端
业务中使用到了co, 进程使用 pm2 管理.node
确保构建脚本可以使用nvm安装nodejs 6.9.5, 本地运行基本okjson
UnhandledPromiseRejectionWarning: Cannot read property 'done' of undefined
复制代码
服务启动时即产生上述报警信息, 服务不可用, 经过搜索发现是存在某个promise最终reject了, 可是没有catch. 知道直接缘由是这样, 但没啥帮助, 我上哪去找这种特色的代码.小程序
考虑断点调试promise
process.on('unhandledRejection', function(reason, p){
console.log('=======================');
console.log(reason);
console.log(p);
});
复制代码
上述代码加到服务开始启动, 本地调试启动, 发现一切正常 -_-bapp
不复现问题, 回顾整个问题, 目测多是测试环境问题, 先看看nodejs版本吧性能
console.log(process.versions)
复制代码
居然nodejs版本仍是旧版本测试
能决定nodejs版本的途径就只有进程启动了, 哪问题就落到 pm2 这边了, 去检查pm2的进程配置spa
> pm2 show myapp_name
│ interpreter │ node
│ interpreter args │ --harmony
....
│ exec mode │ cluster_mode
│ node.js version │ 4.4.2
复制代码
果真版本有问题, 考虑pm2这种进程管理模型, daemon进程启动后, 再逐个启动worker进程, 而 exec mode: cluster_mode
意味着它使用了nodejs的cluster模块来启动子进程.调试
进一步的, cluster启动子进程是用fork()启动的, 子进程的版本和父进程版本应该是一致的. 大几率是这个缘由.
简单重启daemon进程的办法是 pm2 kill
干掉daemon和全部worker进程后, 从新pm2 start
. 一番折腾后的结论:
pm2 kill && pm2 ping
能够重启daemon外, 还能够 pm2 update
它还会使用当前版本pm2pm2 delete app.json && pm2 start app.json
测试环境 重启了pm2 daemon进程后, 启动仍旧是前文遇到的报警, 但 node.js version
输出是符合预期了.
虽然没解决问题, 但升级版本是必须的. 继续看看, 收集线索
如今nodejs版本一致, 可是测试环境报警, 本地不复现, 可能仍是环境问题, 继续看进程配置, 发现 interpreter args: --harmony
这个是旧版本nodejs为了兼容新的特性加的开关, 考虑到错误堆栈是从co中过来的, 查看co的文档
按理v4+以后就不须要加这个开关, 暂且不关心为何加这个开关, 目前能找到的差别就是这个地方, 先本地加上这个开关运行看看
结果复现相同的报警, 本地和测试环境现象一致
接下来就好办了, 到app.json中删除这段配置, pm2 delete app.json && pm2 start app.json
从新启动app, 问题解决.
实际遇到的环境问题可能都是混杂多个关键缘由, 必须得解决全部的缘由才能正常工做.
错误才是常态, 正确是一连串的偶然组合在一块儿
了解cluster的同窗应该知道 fork() 只有一个参数 环境变量, 那就有些奇怪的地方了.
一种多是 pm2 daemon 启动时加上去的, 但也不合逻辑, daemon可能会管理多个项目, 有的是cluster, 有的不是.
只是猜想显然不行, 看源码吧
God.nodeApp = function nodeApp(env_copy, cb){
var clu = null;
console.log('Starting execution sequence in -cluster mode- for app name:%s id:%s',
env_copy.name,
env_copy.pm_id);
if (env_copy.node_args && Array.isArray(env_copy.node_args)) {
// 注意下面这行
cluster.settings.execArgv = env_copy.node_args;
}
env_copy._pm2_version = pkg.version;
try {
// node.js cluster clients can not receive deep-level objects or arrays in the forked process, e.g.:
// { "args": ["foo", "bar"], "env": { "foo1": "bar1" }} will be parsed to
// { "args": "foo, bar", "env": "[object Object]"}
// So we passing a stringified JSON here.
clu = cluster.fork({pm2_env: JSON.stringify(env_copy)});
} catch(e) {
God.logAndGenerateError(e);
return cb(e);
}
复制代码
从新翻看 cluster 的文档, 发现确实存在 cluster.settings
你们好,我是猫眼娱乐前端技术专家-曹宇,我主要负责猫眼娱乐电影选座交易业务前端, 除了你们能看到的各类 Web 页面, 还有小程序端和供应链端. 同时负责猫眼内部的前端基础设施, 质量保证相关工做。
猫眼电影小程序从零发展到票务类别第一, 主要关注点都集中在线上, 此次分享的是一个线上 线下联动的活动, 从开发到上线后遇到的一些有趣的事情, 除了小程序技术的深度应用, 还包括产品 运营层面的思考.
本周六(10月21日)我会作客掘金Bilibili直播间为你们作一场《打码指南:由猫眼线下扫码1分购谈起》的直播。直播中咱们也会送出技术图书,大号定制鼠标垫等奖品,欢迎周六下午你们与咱们一块儿交流。