㈠ 如何在Nodejs中使用緩存
Nodejs可以使用redis緩存。
Redis資料庫採用極簡的設計思想,最新版的源碼包還不到2Mb。其在使用上也有別於一般的資料庫。
node_redis
redis驅動程序多使用 node_redis此模塊可搭載官方的 hiredis C 語言庫 - 同樣是非阻塞的,比使用JavaScript內置的解釋器性能稍好。可選擇將hiredis 與 redis 一同安裝。
npm install hiredis redis
如果 hiredis 安裝成功, node_redis 會默認使用 hiredis, 否則會使用JavaScript的解釋器。
Redis的一個Key不僅可以對應一個String類型的值,還支持hashes, lists, sets, sorted sets, bitmaps等。
比如存/取一組Hash值,Redis中有兩個對應的命令
HMSET key field value [field value ...]、
為一個Key一次設置多個哈希鍵/值, 多用於JSON對象的寫入(序列化的SESSION)。
HGETALL key
讀取一個Key的所有 哈希鍵/值,多用於JSON對象讀取
這兩個命令即是在NodeJS中存取JSON對象的關鍵,
下面是node_reids中對應的例子:
全選復制放進筆記var redis = require("redis"),
client = redis.createClient();
//寫入JavaScript(JSON)對象
client.hmset('sessionid', { username: 'kris', password: 'password' }, function(err) {
console.log(err)
})
//讀取JavaScript(JSON)對象
client.hgetall('sessionid', function(err, object) {
console.log(object)
})
㈡ 為什麼redis在java是同步緩存,而在nodejs是非同步緩存
JAVASCRIPT中是沒有多線程的,所有涉及外部IO的全部都是回調。
這樣的好處是JS天然就是一個不會阻塞的系統,這也是NODEJS現在作為前後端黏合層的原因。
㈢ 請教關於Nodejs多進程共享緩存數據
以正常目前的業務場景來說(非nodejs),一個進程平均是用1.5-3G內存不等.緩存是根據某些特定條件組合生成的key(key的數量稍微有點兒多),需要從MongoDB/Redis讀取數據.
1MB的數據是業務數據傳輸量最大的那種,不是只有這種業務.
場景可以假設為,獲取用戶的一些瀏覽記錄,包含圖片,描述,評測等(描述與評價都算是比較大的傳輸量的數據),每次獲取30條左右.然後再乘以一定的用戶在線數量,這個緩存數據是比較龐大的.先不考慮這個架構是否可以優化.
發這個主題的原因只是想了解到nodejs有沒有什麼成熟方案可以共享進程間的數據
比如
用戶X,訪問站點時,被調度系統分配給A進程獲取了luby的瀏覽歷史,A進程從mongodb獲取到luby的記錄列表進行呈現.這時候用戶Y也想看看luby的瀏覽歷史,這調度系統分配給了B進程.這個時候B進程又要再去mongodb獲取一次.
我期望是B進程可以共享A進程的luby記錄列表
1)降低mongogdb的訪問頻率
2)提高響應速度,因為減少了mongodb查詢,減少了網路傳輸.
㈣ nodejs查看node-cache在哪個問孩子
為什麼不使用現有的Cache存儲系統,比如Redis,比如Memcached。不是說Redis不夠好,只是在處理某些場景中使用的Redis會顯的太「笨重」了——Redis的優勢之一在於能夠供多進程共享,有完善的備份和恢復機制。
但反過來想,如果你的緩存僅供單個進程,單個Node實例使用,並且可以容忍緩存的丟失,承受冷啟動。那麼是值得用不到500行的代碼來搭建一個速度更快的緩存模塊。
㈤ nodejs如何實現
摘要 CommonJS 是一種模塊化的標准,而 NodeJS 是這種標準的實現,每個文件就是一個模塊,有自己的作用域。在一個文件裡面定義的變數、函數、類,都是私有的,對其他文件不可見。
㈥ nodejs socket怎麼主動刷新緩存區數據
清空socket緩存區的數據的方法
由於socket是以數據流的形式發送數據,接收方不知道對方一次性發送了多少數據,也能保證對方一次性發送的數據能在同一刻接收到,所以Receive方法是這么工作的:
接受一個byye[]類型的參數作為緩沖區,在經過一定的時間後把接收到的數據填充到這個緩沖區裡面,並且返回實際接收到數據的長度,這個實際接收到的數據長度有可能為0(沒有接收到數據)、大於0小於緩沖區的長度(接收到數據,但是沒有我們預期的多)、等於緩沖區的長度(說明接收到的數據大於等於我們預期的長度)。
每次接收緩沖區都用同一個byte[] byteMessage,並且你沒有檢查接收到的數據長度,所以第一次你接收到的數據是123456,第二次你只接收到了8,但是緩沖區裡面還有23456,所以加起來就是823456了。
socket接收緩沖區的大小有講究,設置大了接收起來慢,因為它要等盡可能多的數據接收到了再返回;設置小了需要重復多次調用接收方法才能把數據接收完,socket有個屬性,標識了系統默認的接收緩沖區大小,可以參考這個!
還有就是用recv讀取,但是由於不知道緩存里有多少數據,如果是阻塞模式,到最後必然等到超時才知道數據已經讀取完畢,這是個問題。
另一個是用fgetc,通過返回判斷是否是feof:
whlie (1) { a=fgetc(f);if (feof(f)) break;//…
b=fgetc(f);if (feof(f)) break;//…}當然,我不知道讀取完畢後最後一次調用fgetc會不會堵塞,需要測試。
在非阻塞模式下,我們用recv就可以輕松搞定了,但是阻塞模式下,由於我們不知道緩沖區有多少數據,不能直接調用recv嘗試清除。
使用一個小小的技巧,利用select函數,我們可以輕松搞定這個問題:
select函數用於監視一個文件描述符集合,如果集合中的描述符沒有變化,則一直阻塞在這里,直到超時時間到達;在超時時間內,一旦某個描述符觸發了你所關心的事件,select立即返回,通過檢索文件描述符集合處理相應事件;select函數出錯則返回小於零的值,如果有事件觸發,則返回觸發事件的描述符個數;如果超時,返回0,即沒有數據可讀。
重點在於:我們可以用select的超時特性,將超時時間設置為0,通過檢測select的返回值,就可以判斷緩沖是否被清空。通過這個技巧,使一個阻塞的socket成了『非阻塞』socket.
現在就可以得出解決方案了:使用select函數來監視要清空的socket描述符,並把超時時間設置為0,每次讀取一個位元組然後丟棄(或者按照業務需要進行處理,隨你便了),一旦select返回0,說明緩沖區沒數據了(「超時」了)。
㈦ nodejs 模塊會緩存,但執行是會再次解析么
Node.js中模塊可以通過文件路徑或名字獲取模塊的引用。模塊的引用會映射到一個js文件路徑,除非它是一個Node內置模塊。
Node的內置模塊公開了一些常用的API給開發者,並且它們在Node進程開始的時候就預載入了。
㈧ nodejs orm redis怎麼做緩存
Nodejs可以使用redis緩存。 Redis資料庫採用極簡的設計思想,最新版的源碼包還不到2Mb。其在使用上也有別於一般的資料庫。 node_redis redis驅動程序多使用 node_redis此模塊可搭載官方的 hiredis C 語言庫 - 同樣是非阻塞的
㈨ nodejs fs 文件流傳輸要不要緩存區
nodejs的fs模塊並沒有提供一個的方法,但我們可以很容易的實現一個,比如:
var source = fs.readFileSync('/path/to/source', {encoding: 'utf8'});
fs.writeFileSync('/path/to/dest', source);
這種方式是把文件內容全部讀入內存,然後再寫入文件,對於小型的文本文件,這沒有多大問題,比如grunt-file-就是這樣實現的。但是對於體積較大的二進制文件,比如音頻、視頻文件,動輒幾個GB大小,如果使用這種方法,很容易使內存「爆倉」。理想的方法應該是讀一部分,寫一部分,不管文件有多大,只要時間允許,總會處理完成,這里就需要用到流的概念。
如上面高大上的圖片所示,我們把文件比作裝水的桶,而水就是文件里的內容,我們用一根管子(pipe)連接兩個桶使得水從一個桶流入另一個桶,這樣就慢慢的實現了大文件的復制過程。
Stream在nodejs中是EventEmitter的實現,並且有多種實現形式,例如:
http responses request
fs read write streams
zlib streams
tcp sockets
child process stdout and stderr
上面的文件復制可以簡單實現一下:
var fs = require('fs');
var readStream = fs.createReadStream('/path/to/source');
var writeStream = fs.createWriteStream('/path/to/dest');
readStream.on('data', function(chunk) { // 當有數據流出時,寫入數據
writeStream.write(chunk);
});
readStream.on('end', function() { // 當沒有數據時,關閉數據流
writeStream.end();
});
上面的寫法有一些問題,如果寫入的速度跟不上讀取的速度,有可能導致數據丟失。正常的情況應該是,寫完一段,再讀取下一段,如果沒有寫完的話,就讓讀取流先暫停,等寫完再繼續,於是代碼可以修改為:
var fs = require('fs');
var readStream = fs.createReadStream('/path/to/source');
var writeStream = fs.createWriteStream('/path/to/dest');
readStream.on('data', function(chunk) { // 當有數據流出時,寫入數據
if (writeStream.write(chunk) === false) { // 如果沒有寫完,暫停讀取流
readStream.pause();
}
});
writeStream.on('drain', function() { // 寫完後,繼續讀取
readStream.resume();
});
readStream.on('end', function() { // 當沒有數據時,關閉數據流
writeStream.end();
});
或者使用更直接的pipe
// pipe自動調用了data,end等事件
fs.createReadStream('/path/to/source').pipe(fs.createWriteStream('/path/to/dest'));
下面是一個更加完整的復制文件的過程
var fs = require('fs'),
path = require('path'),
out = process.stdout;
var filePath = '/Users/chen/Movies/Game.of.Thrones.S04E07.1080p.HDTV.x264-BATV.mkv';
var readStream = fs.createReadStream(filePath);
var writeStream = fs.createWriteStream('file.mkv');
var stat = fs.statSync(filePath);
var totalSize = stat.size;
var passedLength = 0;
var lastSize = 0;
var startTime = Date.now();
readStream.on('data', function(chunk) {
passedLength += chunk.length;
if (writeStream.write(chunk) === false) {
readStream.pause();
}
});
readStream.on('end', function() {
writeStream.end();
});
writeStream.on('drain', function() {
readStream.resume();
});
setTimeout(function show() {
var percent = Math.ceil((passedLength / totalSize) * 100);
var size = Math.ceil(passedLength / 1000000);
var diff = size - lastSize;
lastSize = size;
out.clearLine();
out.cursorTo(0);
out.write('已完成' + size + 'MB, ' + percent + '%, 速度:' + diff * 2 + 'MB/s');
if (passedLength < totalSize) {
setTimeout(show, 500);
} else {
var endTime = Date.now();
console.log();
console.log('共用時:' + (endTime - startTime) / 1000 + '秒。');
}
}, 500);
可以把上面的代碼保存為.js試驗一下
我們添加了一個遞歸的setTimeout(或者直接使用setInterval)來做一個旁觀者,每500ms觀察一次完成進度,並把已完成的大小、百分比和復制速度一並寫到控制台上,當復制完成時,計算總的耗費時間,效果如圖:
我們復制了一集1080p的權利的游戲第四季第7集,大概3.78G大小,由於使用了SSD,可以看到速度還是非常不錯的,哈哈哈~
復制完成後,顯示總花費時間
結合nodejs的readline, process.argv等模塊,我們可以添加覆蓋提示、強制覆蓋、動態指定文件路徑等完整的復制方法,有興趣的可以實現一下,實現完成,可以
ln -s /path/to/.js /usr/local/bin/my
這樣就可以使用自己寫的my命令替代系統的cp命令
㈩ 想問一下 nodejs 內存要怎麼查看
varcookie=require('cookie');mole.exports=function(req,res,conf,views,db){..varbody=req.body,.id=req.ids[0],.usid=cookie.parse(req.headers.cookie).usid;..functionredirect(){.res.writeHead(302,{'location':'/accounts'});.res.end();..}..functionjoinpage(){.res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});.res.write(views.ACCOUNTS_JOIN);.res.write(views.unit({id:'accounts_menu',name:'accounts_menu',..options:{.class_id:id..}.}));.res.write(views.unit({id:'accounts_join',name:'accounts_join',options:{..action:'/accounts/'+id+'/join',..num:'0'}.}));.res.end(views.FOOTER);..}..db.session(usid,function(state){.//已經建立會話.if(state){joinpage();return;.}.//沒有建立會話.redirect();..});};//////////////////////////////////////////////////////////////////////////////////////////////////////////這段代碼,是nodejs其中一個路由處理函數.使用到了views視圖模型,db資料庫模型,以及conf全局配置文件.並且使用了cookie模塊來解析會話ID.views視圖模型:生產HTML界面[可以隨時切換到PC或者移動HTML,介面一致]db數據模型:生產資料庫數據conf全局配置文件:你所需要的全局環境內容代碼的功能:檢測請求.是否建立會話?..是,跳轉到"/"路由..否,為用戶顯示登錄界面其中views負責生產視圖界面,在views模型中緩存了大量的常量,類似ACCOUNTS_JOIN,是頁面布局。對於其中的動態內容,採用facebook的bigpipe技術。views.unit(/*id,name,css,js,content*/)輸出script片段,分流到瀏覽器渲染。整個伺服器端在啟動時渲染完畢所有的頁面布局體,並緩存到views模型中,動態內容由bigpipe發送到前端渲染。