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分購談起》的直播。直播中咱們也會送出技術圖書,大號定製鼠標墊等獎品,歡迎週六下午你們與咱們一塊兒交流。