node项目架构与优化
為什么要用node
1、前后端耦合太緊密,中間加一層node,還要給前端裝一些亂七八糟的東西? java啥的服務環境。還有后臺返回接口的時候不管前端需不需要那些接口一起返回,其實只用到1~2 條數據。本來ajax就非常消耗時的事,就用其中一條,用node做一層中間層處理把沒用的接口剔除掉。
2、比如:一個10天項目,后臺開發6天,前臺2天,測試2天。后臺開發時,沒有接口,前端得等著后臺的接口,如果后臺某種情況推遲了一天,前端就1天開發,測試要2天,肯定前端開發不完。使用node我們可以并行開發,提高開發效率。
3、proxy 代理層? ? java->node? ? 前端->node? 這種情況叫BFF,后臺是沒有跨域的。做了一層中間代理,可以自己控制路由,前端請求發給node,就不會出現跨域的問題。node socket io 實時通訊。
4、node容錯,性能難做。
node異步IO原理淺析及優化方案
-
異步IO的是與非
前端通過異步IO可以消除UI阻塞。
假設請求資源A的時間為M,請求資源B的時間為N,那么同步的請求耗時就為M+N,如果采用異步的方式占用時間為MAX(M,N)。
隨著業務的復雜,會引入分布式系統,時間會線性的增加M+N+...和MAX(M,N,...),這會放大同步和異步之間的差異。
I/O是昂貴的,分布式I/O是更昂貴的。
一些底層知識
1、
CPU是鐘周期:1/CPU主頻->1s/3.1GHz
一級CPU是鐘周期:3.5GHz? ?1/3.5*3? io時間
2、
p是并行系統鐘的處理器數量;
f=ws/w為串行部分的比例;
我們分布到其他機器里,每個機器都用同樣的代碼。網絡要請求這文件,就比較慢 整個時間就比較長。
并不是所有的所有并行的好,也并不少所有串行就好,分情況。系統會自動根據情況來判斷使用并行還是串行。
3、操作系統對計算機進行來抽象,將所有輸入輸出設備抽象為文件。內核在進行文件I/O操作時,通過文件描述符進行管理。應用程序如果需要進行I/O需要打開文件描述符,在進行文件和數據的讀寫。異步IO不帶數據直接返回,要獲取數據還需要通過文件描述符再次讀取。
?
NodeJS使用與IO密集型不適用于CPU密集型
比如銀行,每次計算價格,java是多線程可以處理多個任務,而Nodejs是單線程用異步不停的寫,寫發上也非常復雜。可以有框架處理單線程問題,但是性能上還是不如java。
-
Node對異步IO實現
完美的異步IO應該是應用程序發起阻塞調用,無需通過便利或者事件幻想等方式輪詢。
前端的event loop跟node event loop不一樣,前端比node event loop還要復雜一些。node程序進來不停的轉,就等于我們把米放到電飯煲里,定好時間,我們去忙別的,等他做好之后,會提示,已經做好了。
-
幾個特殊對API
1、setTimeout和setInterval線程池不參與
2、process.nextTick()實現類似setTimeout(function(){},0);每次調用放入隊列中,在下一輪循環中取出。
3、setImmediate();比provess.nextTick()優先級低
4、Node如何實現一個Sleep?
async function test(){console.log('hello');await seelp(1000);console.log('word'); } function seelp(time){return new Promise(resolve=>setTimeout(resolve,time)) } test()
?
-
函數式編程在Node中對應用
1、高階函數:可以將函數作為輸入或者返回值,形成一種后續傳遞風格的結果接受方式,而非單一的返回值形成。后續傳遞風格的程序將函數業務重點從返回值傳遞到回調函數中。
app.use(function(){//todo }) var emitter = new event.eventEmitter; emitter.on(function(){//todo })2、偏函數:指定部分參數產生一個新的定制函數的形式就是偏函數。node中異步編程非常常見,我們通過哨兵變量會很容易造成業務的混亂。underscore,after變量。
-
常用的Node控制異步API的技術手段
1、step、wind(提供等待的異步庫)、bigpipe、Q.js
2、Async、Await
3、Promise/Defferred是一種先執行異步調用,延遲傳遞的處理方式。Promise是高級接口,事件是低級接口。低級接口可以構建更多復雜的場景,高級接口一旦定義,不太容易變化,不再有低級接口的靈活性,但對于解決問題非常有效。
4、由于Node基于V8的原因,目前還不支持協程。協程不是進程或線程,其執行過程更類似于子例程,或者說不帶返回值的函數調用。
一個程序可以包含多個協程,可以對比一個進程包含多個線程。來比較協程和線程。我們知道多個線程相對獨立,有自己的上下文,切換受系統控制;而協程也相對獨立,有自己的上下文,但是其切換由自己控制,由當前協程切換到其他協程有當前協程來控制。
內存管理與優化
?V8垃圾回收機制
node使用javascript在服務端操作大內存對象受到了一定的限制,64位系統下約為1.4GB,32位系統是0.7GB
process.memoryUsage->rss、heaptTotal、heapUsed
V8的垃圾回收策略主要基于分代式垃圾回收機制。在自動垃圾回收的演變過程中,人們發現沒有一種垃圾回收算法能夠勝任所有場景。V8內存分為新生代和老生代。新生代為存活時間較短對象,老圣代為存活時間較長的對象。
Scavenge算法
在分帶基礎上,新生代的對象主要通過Scavenge算法進行垃圾回收,在具體實現時主要采用cheney算法,cheney算法是一種采用復制的方法實現的垃圾回收算法。它將內存一分為二,每一個空間稱為semispace。這兩個semispace中一個處于使用,一個處于閑置。處于使用的稱之為From,檢查From存活對象復制到To。非存活被釋放。然后互換位置。再次進行回收,發現被回收過直接晉升,或者發現To空間已經使用來超過25%。他的缺點只能使用堆內存的一半,這是一個典型的空間換時間的辦法,但是新生代生命周期較短,恰恰就適合這個算法。
老生代空間生成完成肯定要有東西管理它,就有來mark-sweep和mark-compact
V8老生代主要采用mark-sweep和mark-compact,在使用Scavenge不合適。一個是對象較多需要賦值量太大而且還是沒能解決空間問題。Mark-Sweep是標記清除,標記那些死亡的對象,然后清除。但是清除過后出現內存不連續的情況,所有我們要使用Mark-Compact,他是基于mark-sweep演變而來的,它現將活著的對象移到一邊,移動完成后,直接清理邊界外的內存。當CPU空間不足的時候會非常高效。V8還引入來延遲處理,增量處理,并計劃引入并標記處理。
常見的內存泄漏問題
1、無限制增長的數組
2、無限制設置屬性和值
3、任何模塊內的私有變量和方法均是永駐內存的a=null
4、大循環,無GC(垃圾回收機制)機會
內存泄漏分析
node-inspector
console.log("Server PID",process.pid);
sodu node --inspect app.js
whie true;do curl "http:localhost:1337/";done
top -pid 2322
大規模Node站點結構原理分析
經典的MVC框架
model-view-Controller
javaweb多層架構
node 集群應用
? 預備上線
1、前端工程化的搭載動態文件的MAP分析壓縮打包合并至CDN
2、單側、壓力測試、性能分析工具發現Bug
3、編寫nginx-conf實現負載均衡和反向代理
4、PM2啟動應用生序小流量灰度上線,修復Bug
5、上線前的不眠夜、你見過凌晨5點的北京么?
多線程
1、master進程均為主進程,Fork可以創造主進程。
2、通過child_process可以和NET模塊組合,可以創建多個線程并監聽統一端口。通過句柄傳遞完成自動啟動、發射自殺信號、限量重啟、負載均衡。
3、node默認的機制是采用操作系統的搶占式策略。閑著的進程爭搶任務,但是會造成CPU閑置的IO暫時并未閑置。Node后來引入來Round-Robin機制,也叫輪詢調度。主進程接受任務,在發。
4、每個子進程做好自己的事,然后通過進程間通信來將他們鏈接起來。這符合Unix的設計理念,每個進程只做一件事,并做好。將福啊分解為簡單,將簡單組合程強大。
PM2
pm2是一個自帶負載均衡功能的node應用的進程管理器。
當你要把你的獨立代碼利用全部的服務器上的所有CPU,并保證進程永遠活著,0秒重載。
1、內建負載均衡(使用node cluster集群模塊)
2、后臺運行
3、0秒停機重仔
4、具有Ubuntu和CentOS的啟動腳本
5、停止不穩定的進程(避免無限循環)
6、控制臺檢測
7、提供HTTP API
8、遠程控制和實時的接口API(Nodejs 模塊,允許和PM2進程管理交互)
測試過Nodejs v0.11 v0.10 v0.8版本,兼容CoffeeScript,基于linux和MacOs
我之前是前端連java感覺還可以,如果我中間加一層node,是不是就變慢了呢,并不是,首先java跟node在同樣一個機房他倆請求的時間被嚴格限制在1ms(毫秒),甚至一些團隊100ms已經頂天了,300ms服務肯定有問題。用戶肯定無法感知的,node和java走了一次http,會有3次握手,即使是毫秒也是一次浪費,node和java 走的是Linux Virtual Server(Linux虛擬服務器)通信。
?
?
?
?
轉載于:https://www.cnblogs.com/139199228-haicao/p/9193753.html
總結
以上是生活随笔為你收集整理的node项目架构与优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 区块链100讲:据说,80%的人都搞不懂
- 下一篇: 机器学习:数据预处理之独热编码(One-