在網上看到一些帖子,吐糟,質疑nodejs 程序的穩定性,為什麼呢?其一,可能這個和javascript有關吧,node是拿去實現的,而javascript又被稱為是「世界上誤解最深的語言」,我們可以去看看nodejs 創始人的說法,可以去看看知乎的這篇文章,為什麼node 用javascript去實現,其二,nodejs 畢竟還年輕,而且官網在部分模塊也標注了此模塊的目前的狀態。
這2天我抽了點時間思考了下這個問題,我覺得我們程序首先功能應該是獨立的,就是一個功能出異常了,不應該去影響另外一個正常的功能,不應該將整個程序都崩潰掉,其次,即使是程序崩潰了,我們也應該有一個讓程序自動啟動,另外,應該去記錄日誌,方便我們跟蹤問題。我覺得主要可以從以下方面提高nodejs 穩定性:
1)保持良好的代碼結構:
我們知道node是單線程,非阻塞io,默認就是非同步,通過回調的方式處理後面的流程,如果嵌套的層次太多了,勢必會引起代碼邏輯結構的混亂,也不利於維護和升級,可以採用async這個非同步流程式控制制模塊,來理清我們的代碼邏輯。
2)使用 process.on('uncaughtException', function(err){...}); 來處理未被捕捉的錯誤。
3)使用try~catch 來捕獲異常:
這個只能解決一部分問題,不是萬能的,在上面說到因為node是單線程,非阻塞io,默認就是非同步,通過回調的方式處理後面的流程,try~catch 是不能捕獲的callback 裡面的error的錯誤的,怎麼捕獲到callback裡面的錯誤呢 ? 可以採用domain模塊
4)使用domain模塊來處理程序的異常
先看看對domain的解釋:domain是 EventEmitter類的一個子類。監聽它的error事件來處理它捕捉到的錯誤。 它提供了一種方式,即以一個單一的組的形式來處理多個不同的IO操作。如果任何一個注冊到domain的事件觸發器或回調觸發了一個『error』事件,或者拋出一個錯誤,那麼domain對象將會被通知到。而不是直接讓這個錯誤的上下文從`process.on('uncaughtException')'處理程序中丟失掉,也不會致使程序因為這個錯誤伴隨著錯誤碼立即退出。
如何使用domain 模塊呢?看一個例子:
serverDomain.run(function() {
// 伺服器在serverDomain的作用域內被創建
http.createServer(function(req, res) {
// req和res同樣在serverDomain的作用域內被創建
// 但是,我們想對於每一個請求使用一個不一樣的域。
// 所以我們首先創建一個域,然後將req和res添加到這個域上。
var reqd = domain.create();
reqd.add(req);
reqd.add(res);
reqd.on('error', function(er) {
console.error('Error', er, req.url);
try {
res.writeHead(500);
res.end('Error occurred, sorry.');
} catch (er) {
console.error('Error sending 500', er, req.url);
}
});
}).listen(1337);
});
```
說明:首先創建一個域(domain.create()),然後將需要監控的分發器添加到該域上,最後給域綁定一個錯誤事件,這樣就可以監控了。
再看一個例子:
var d = domain.create();
d.on('error', function(er) {
console.error('Caught error!', er);
});
d.run(function() {
process.nextTick(function() {
setTimeout(function() { // 模擬幾個不同的非同步的東西
fs.open('non-existent file', 'r', function(er, fd) {
if (er) throw er;
// 繼續。。。
});
}, 100);
});
});
說明:首先創建一個域,給域綁定一個錯誤事件,然後在域的上下文提供可以運行的函數
如果對於回調呢?可以這么使用
var d = domain.create();
function readSomeFile(filename, cb) {
fs.readFile(filename, 'utf8', d.bind(function(er, data) {
// if this throws, it will also be passed to the domain
return cb(er, data ? JSON.parse(data) : null);
}));
}
d.on('error', function(er) {
// an error occurred somewhere.
// if we throw it now, it will crash the program
// with the normal line number and stack message.
});
當然也可以這么使用
var d = domain.create();
function readSomeFile(filename, cb) {
fs.readFile(filename, 'utf8', d.intercept(function(data) {
return cb(null, JSON.parse(data));
}));
}
d.on('error', function(er) {
// an error occurred somewhere.
// if we throw it now, it will crash the program
// with the normal line number and stack message
});
這個函數與domain.bind(callback)幾乎一模一樣。但是,除了捕捉被拋出的錯誤外,它還會攔截作為第一參數被傳遞到這個函數的Error對象。
5)使用log4js 模塊記錄日誌
log4js 是一個非常強大的日誌管理工具,在可以看看github這個項目: https://github.com/nomiddlename/log4js-node
6)使用forever 模塊來管理nodejs
forever 是服務端管理nodejs 的一個模塊,一個命令行工具,能夠啟動,停止app 應用。forever完全是基於命令行操作,在forever進程管理之下,創建node的子進程,通過monitor監控node子進程的運行情況,一旦文件更新,或者進程掛掉,forever會自動重啟node伺服器,確保應用正常運行。非常的好用.
可以關注下這個項目:https://github.com/nodejitsu/forever
但是forever 也不是萬能的,也由下面這些問題:
有限的監控和日誌功能
進程管理配置的支持差
不支持集群
代碼庫老化(意味著在升級node.js時頻繁的失敗)
2. 如何提高NodeJS程序的穩定性
我覺得我們程序首先功能應該是獨立的,就是一個功能出異常了,不應該去影響另外
一個正常的功能,不應該將整個程序都崩潰掉,其次,即使是程序崩潰了,我們也應該有一個讓程序自動啟動,另外,應該去記錄日誌,方便我們跟蹤問題。我覺得
主要可以從以下方面提高nodejs 穩定性:
1)保持良好的代碼結構:
我們知道node是單線程,非阻塞io,默認就是非同步,通過回調的方式處理後面的流程,如果嵌套的層次太多了,勢必會引起代碼邏輯結構的混亂,也不利於維護和升級,可以採用async這個非同步流程式控制制模塊,來理清我們的代碼邏輯。
2)使用 process.on('uncaughtException', function(err){...}); 來處理未被捕捉的錯誤。
3)使用try~catch 來捕獲異常:
這個只能解決一部分問題,不是萬能的,在上面說到因為node是單線程,非阻塞io,默認就是非同步,通過回調的方式處理後面的流程,try~catch
是不能捕獲的callback 裡面的error的錯誤的,怎麼捕獲到callback裡面的錯誤呢 ? 可以採用domain模塊
4)使用domain模塊來處理程序的異常
先看看對domain的解釋:domain是 EventEmitter類的一個子類。監聽它的error事件來處理它捕捉到的錯誤。 它
提供了一種方式,即以一個單一的組的形式來處理多個不同的IO操作。如果任何一個注冊到domain的事件觸發器或回調觸發了一個『error』事件,或
者拋出一個錯誤,那麼domain對象將會被通知到。而不是直接讓這個錯誤的上下文從
`process.on('uncaughtException')'處理程序中丟失掉,也不會致使程序因為這個錯誤伴隨著錯誤碼立即退出。
5)使用log4js 模塊記錄日誌
log4js 是一個非常強大的日誌管理工具,在可以看看github這個項目: https://github.com/nomiddlename/log4js-node
6)使用forever 模塊來管理nodejs
forever 是服務端管理nodejs 的一個模塊,一個命令行工具,能夠啟動,停止app 應用。forever完全是基於命令行操作,在forever進程管理之下,創建node的子進程,通過monitor監控node子進程的運行情況,一旦文件更新,或者進程掛掉,forever會自動重啟node伺服器,確保應用正常運行。非常的好用.
3. 如何配置bowerrc文件代理
安裝之前檢查nodejs如果沒安裝nodejs按照以下步驟安裝$su-$yuminstallopenssl-devel$cd/usr/local/src$wgetprivate-bower-config.json將以下內容粘貼進去:{"port":5678,"registryFile":"./private-bower/bowerRepository.json","disablePublic":false,"publicRegistry":"/packages/","repositoryCache":{"git":{"enabled":true,"cacheDirectory":"./private-bower/gitRepoCache","host":"localhost","port":6789},"svn":{"enabled":true,"cacheDirectory":"./private-bower/svnRepoCache","host":"localhost","port":7891}},"log4js":{"enabled":true,"configPath":"./private-bower/log4js.conf.json"}}$vim/data/private-bower/log4js.conf.json{"appenders":[{"type":"dateFile","filename":"./private-bower/private-bower.log","pattern":"-yyyy-MM-dd","alwaysIncludePattern":false},{"type":"console"}],"replaceConsole":true}啟動private-bower$sudosu-$cd/data$private-bower--config./private-bower-config.json[2014-06-3010:00:22.481][INFO]console-[bower]Refreshingpublicpackages[2014-06-3010:00:22.512][INFO]console-[bower]Bowerserverstartedonport5678[2014-06-3010:00:22.538][INFO]console-[bower]Startinggitcacheserver[2014-06-3010:00:22.543][INFO]console-[bower]Startingsvncacheserver[2014-06-3010:01:09.167][INFO]console-[bower]Loadedpublicpackages確保private-bower正常啟動:打開一個新窗口來訪問:$lynx會顯示:ForkmeonGitHubPrivateBower____________________.LoadingPackages{{package.name}}hits:{{package.hits}}{{package.repo}}CreatedbyBarnaTothBarnaTóth如果是這樣,就安裝完畢了客戶端測試$sudosu-$npminstall-gbower$su-wlsuser$bowerhelp$vim.bowerrc{"registry":"http://:5678"}$cd$bowerinstalljquery