Node.js
是從純前端走向更高階層的前端,以及全棧工程師的惟一快速途徑Node.js
就是運行在服務端的 JavaScript
Node.js
是一個基於Chrome JavaScript
運行時創建的一個平臺Node.js
是一個事件驅動I/O
服務端JavaScript
環境,基於Google
的V8
引擎,V8
引擎執行Javascript
的速度很是快,性能很是好PHP
、Python
或Ruby
等動態編程語言,而後你想建立本身的服務,那麼Node.js
是一個很是好的選擇Node.js
是運行在服務端的 JavaScript
,若是你熟悉Javascript
,那麼你將會很容易的學會Node.js
Node.js
也是一個很是好的選擇Node.JS
適合運用在高併發、I/O
密集、少許業務邏輯的場景Node.js
的模塊組成以下:Node.js
的運行機制JavaScript
腳本Node API
libuv
庫負責Node API
的執行。它將不一樣的任務分配給不一樣的線程,造成一個EventLoop
(事件循環),以異步的方式將任務的執行結果返回給V8引擎。V8
引擎再將結果返回給用戶。(Event Loop)
Nodejs
執行以後會初始化一個事件循環,執行代碼程序(這些程序可能會形成異步調用、定時器或者process.nextTick()
),而後開始執行事件循環。各個階段執行的任務以下:php
timers 階段
: 這個階段執行setTimeout
和setInterval
預約的callback
;I/O callbacks
階段: 執行除了close
事件的callbacks
、被timers
設定的callbacks
、setImmediate()
設定的callbacks
這些以外的callbacks
;idle, prepare
階段: 僅node內部使用;poll
階段: 獲取新的I/O事件, 適當的條件下node
將阻塞在這裏;check
階段: 執行setImmediate()
設定的callbacks
;close callbacks
階段: 執行socket.on('close', ...)
這些 callback
process.nextTick()
不屬於上面的任何一個phase
,它在每一個phase
結束的時候都會運行。也能夠認爲,nextTick
在下一個異步方法的事件回調函數調用前執行。TIPS:
Node.js
中的事件循環機制不會掉頭,只會由上往下,循環執行。
在Node.js
中,絕大部分API
都是異步的,有一個很形象的故事描述了JAVA和Node.js
的區別,JAVA
是一個餐廳100
個服務員對應100
客戶,Node.js
是一個服務員玩命幹,也對應100
個客戶,上菜的速度很大一部分取決於廚師的作菜速度
I/O
操做完以後呢?Node.js
的I/O
處理完以後會有一個回調事件,這個事件會放在一個事件處理隊列裏頭,在進程啓動時node會建立一個相似於While(true)
的循環,它的每一次輪詢都會去查看是否有事件須要處理,是否有事件關聯的回調函數須要處理,若是有就處理,而後加入下一個輪詢,若是沒有就退出進程,這就是所謂的「事件驅動」。這也從Node
的角度解釋了什麼是」事件驅動」。在node.js
中,事件主要來源於網絡請求,文件I/O
等,根據事件的不一樣對觀察者進行了分類,有文件I/O觀察者,網絡I/O觀察者。事件驅動是一個典型的生產者/消費者模型,請求到達觀察者那裏,事件循環從觀察者進行消費,主線程就能夠快馬加鞭的只關注業務不用再去進行I/O
等待。前端
Node
公開宣稱的目標是 「旨在提供一種簡單的構建可伸縮網絡程序的方法」。咱們來看一個簡單的例子,在 Java和 PHP 這類語言中,每一個鏈接都會生成一個新線程,每一個新線程可能須要2MB的配套內存。在一個擁有8GBRAM的系統上,理論上最大的併發鏈接數量是4,000
個用戶。隨着您的客戶羣的增加,若是但願您的Web應用程序支持更多用戶,那麼,您必須添加更多服務器。因此在傳統的後臺開發中,整個Web應用程序架構(包括流量、處理器速度和內存速度)中的瓶頸是:服務器可以處理的併發鏈接的最大數量。這個不一樣的架構承載的併發數量是不一致的。Node
聲稱它不容許使用鎖,它不會直接阻塞 I/O
調用。Node
在每一個鏈接發射一個在 Node 引擎的進程中運行的事件,而不是爲每一個鏈接生成一個新的 OS 線程(併爲其分配一些配套內存)。nodejs
的機制是單線程,這個線程裏面,有一個事件循環機制,處理全部的請求。在事件處理過程當中,它會智能地將一些涉及到IO、網絡通訊等耗時比較長的操做,交由worker-threads
去執行,執行完了再回調,這就是所謂的異步IO非阻塞吧。可是,那些非IO操做,只用CPU計算的操做,它就本身扛了,好比算什麼斐波那契數列之類。它是單線程,這些本身扛的任務要一個接着一個地完成,前面那個沒完成,後面的只能乾等。所以,對CPU要求比較高的CPU密集型任務多的話,就有可能會形成號稱高性能,適合高併發的node.js服務器反應緩慢。Node.js
高併發使用Nginx+pm2
,pm2
中能夠開啓多線程負載均衡,模式分兩種:pm2
簡介:PM2
是node
進程管理工具,能夠利用它來簡化不少node
應用管理的繁瑣任務,如性能監控、自動重啓、負載均衡等,並且使用很是簡單。
下面就對PM2進行入門性的介紹,基本涵蓋了PM2的經常使用的功能和配置。node
fork
模式,單實例多進程,經常使用於多語言混編,好比php、python
等,不支持端口複用,須要本身作應用的端口分配和負載均衡的子進程業務代碼。缺點就是單服務器實例容易因爲異常會致使服務器實例崩潰。python
cluster
模式,多實例多進程,可是隻支持node
,端口能夠複用,不須要額外的端口配置,0代碼實現負載均衡。優勢就是因爲多實例機制,能夠保證服務器的容錯性,就算出現異常也不會使多個服務器實例同時崩潰。webpack
pm2
部署,默認開啓負載均衡:npm i pm2 -g
$ pm2 start app.js # 啓動app.js應用程序
$ pm2 start app.js -i 4 # cluster mode 模式啓動4個app.js的應用實例 # 4個應用程序會自動進行負載均衡
pm2 start app.js -i max 根據你的cpu數量最大化啓動多線程進行負載均衡
若是要中止全部應用,能夠pm2 stop all
查看進程狀態 pm2 list
pm2真心很好很強大,能夠在線熱更新代碼,更多的指令須要上官網看
pm2
和Nginx
配合upstream my_nodejs_upstream { server 127.0.0.1:3001; } server { listen 80; server_name my_nodejs_server; root /home/www/project_root; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_max_temp_file_size 0; proxy_pass http://my_nodejs_upstream/; proxy_redirect off; proxy_read_timeout 240s; }
特別說明,咱們不建議使用Node.js
做爲底層服務器,更多時候做爲中間件和接入層使用,例如Electron
開發跨平臺應用
Nginx
開啓多線程,負載均衡Nginx
,找到config
文件夾下面的nginx.conf
,修改下面配置文件upstream test{ server 11.22.333.11:6666 weight=1; server 11.22.333.22:8888 down; server 11.22.333.33:8888 backup; server 11.22.333.44:5555 weight=2; } //down 表示單前的server臨時不參與負載. //weight 默以爲1.weight越大,負載的權重就越大 //backup: 其餘所有的非backup機器down或者忙的時候,請求backup機器。因此這臺機器壓力會最輕
nginx
命令彙總 :nginx 服務器重啓命令,關閉 nginx -s reload :修改配置後從新加載生效 nginx -s reopen :從新打開日誌文件 nginx -t -c /path/to/nginx.conf 測試nginx配置文件是否正確 關閉nginx: nginx -s stop :快速中止nginx quit :完整有序的中止nginx 其餘的中止nginx 方式: ps -ef | grep nginx kill -QUIT 主進程號 :從容中止Nginx kill -TERM 主進程號 :快速中止Nginx pkill -9 nginx :強制中止Nginx 啓動nginx: nginx -c /path/to/nginx.conf 平滑重啓nginx: kill -HUP 主進程號
Nginx
多線程負載均衡和部署pm2
負載均衡後的架構圖:Node.js
做爲底層服務器,直接操做數據庫的方式:Node.js
做爲中間件,訪問底層服務器的方式:Apache、Nginx 與 Node.js
之爭高併發下的性能測試對比:
Apache、Nginx 與 Node.js
之爭 i7-2600k
,四核八線程的機器Gentoo Linux
是用於測試的操做系統ApacheBench,2.3 <$Revision: 1748469 $>
咱們能夠從結果中獲得什麼?
全面考慮
PHP 與 Node.js 的對決
Node.js
的生態圈彙總:Node.js
遵循commonJS
規範,要說它的生態圈,第一個確定是webpack
,用很差Node.js
的人確定用很差webpack
,因此說Node.js
的一個突破初級前端工程師的好學習方向express koa koa2 egg
一系列的Node.js
框架,在Restful
架構下使用,完成常規的一些http,ajax
請求響應GraphQL
,GraphQL
是一種 API 所使用的查詢語言,不止Node.js
有,其餘語言也有,不止能夠查詢,還能夠多數據庫CRUD
操做,解決了一部分RestFul
架構帶來的問題mongodb
,非關係型數據庫,輕量級別數據庫,目前Node.js
配合使用的比較多的數據庫,在Node.js
中咱們通常使用 mongoose
這個庫來配合使用sqlite
,SQLite是一個進程內的庫,實現了自給自足的、無服務器的、零配置的、事務性的 SQL 數據庫引擎。它是一個零配置的數據庫,這意味着與其餘數據庫同樣,您不須要在系統中配置。就像其餘數據庫,SQLite 引擎不是一個獨立的進程,能夠按應用程序需求進行靜態或動態鏈接。SQLite 直接訪問其存儲文件。Electron
,跨平臺桌面開發,可使用Node.js
的API,V8的環境也被打包在內。C++
插件,Node.js
的V8環境就是C++寫的,天然也是可使用C++插件Redis
,數據緩存層,Redis支持主從同步。數據能夠從主服務器向任意數量的從服務器上同步,從服務器能夠是關聯其餘從服務器的主服務器。這使得Redis可執行單層樹複製。存盤能夠有意無心的對數據進行寫操做。因爲徹底實現了發佈/訂閱機制,使得從數據庫在任何地方同步樹時,可訂閱一個頻道並接收主服務器完整的消息發佈記錄。同步對讀取操做的可擴展性和數據冗餘頗有幫助。SSR
, 以React
爲例,在中間層對代碼進行注水,在客戶端對代碼脫水,實現部分首屏SSR
,優化首屏渲染時間。websocket
通信等puppeteer
爬蟲Node.js
在目前前端的開發中,是一項不可或缺的技能,它也是讓咱們走向真正全棧工程師的路不那麼陡峭Node.js
適用場景,非密集型計算型Node.js
最核心的部分不止是RestFul
架構的那一套接受請求,返回數據。還有文件IO
,流,Buffer
,redis層
這一類的操做Node.js
配合Nginx
進行負載均衡,不只能提高性能,更能替後端真正減輕不少負擔,完成許多特定的需求。Node.js
在作接入層,好比Electron
中,能夠調用不少Node API
,完成渲染進程不能作的事情,例如文件io
,buffer
操做等今天因爲時間有限,不少東西都沒有細化下去寫,可能仍是有很多漏掉的,之後都會慢慢補上,走過路過,點點贊,我們永遠都是A