nodejs 服务器怎么导入qs_nodejs基本原理总结
? ?戳藍(lán)字「前端技術(shù)優(yōu)選」關(guān)注我們哦!
一. nodejs背景
先來說說nodejs最常被提到的幾個關(guān)鍵詞,“單線程”,“非阻塞異步IO”,“事件循環(huán)”。接下來主要來通過這幾個關(guān)鍵字總結(jié)一下nodejs的內(nèi)在原理,以及引申出的一些問題。
二. nodejs是單線程嗎?
如果說nodejs是單線程語言,可以想象一下,一個單實(shí)例的nodejs的服務(wù)器同時接受100個用戶請求時,第100個用戶的請求要等前面99的用戶處理完成才能得到處理,如果每個用戶的請求要0.3秒,第100個用戶需要30秒的等待,這顯然和我們的實(shí)際情況并不符合,所以說,nodejs并不是單純的單線程。
那為什么說nodejs是單線程語言呢?而是因為nodejs中javascript代碼的執(zhí)行是單線程,怎么理解這句話,看下面代碼。
console.log(執(zhí)行結(jié)果:
$上面的代碼中,setTimeout的回調(diào)代碼在while執(zhí)行4秒期間,計時器已經(jīng)是過了兩秒的,而'javascript setTimeout'這一句打印卻在'javascript end'之后,即使計時器在兩秒后回調(diào)代碼應(yīng)該被執(zhí)行時,因為javascript的線程處于非空閑狀態(tài),而不能輸出'javascript setTimeout',javascript代碼是單線程這樣理解。
三. nodejs的異步IO
再拿上面的例子來看,當(dāng)100個用戶請求同時被接受到時,當(dāng)需要IO(網(wǎng)絡(luò)IO/文件IO)操作時,單線程的javascript并不會停下來等待IO操作完成,而是“事件驅(qū)動”開始介入,javascript執(zhí)行線程繼續(xù)執(zhí)行未完的javascript代碼,當(dāng)執(zhí)行完成后該線程處于空閑狀態(tài),可以看下面這一段代碼示例。
// http.js// req.jsnode http.js // 啟動服務(wù)器node req.js // 發(fā)起100個請求
可以看出100個請求均是在請求返回之前非常短的時間都被得到了處理,而返回則均在請求之后,并非請求按接收順序依次等待各個IO得到處理后依次返回。
四. 事件循環(huán)
說到事件循環(huán),在上面的請求中,100個請求的都在非常短的時間得到了處理,而后請求又各自得到了回復(fù),可以思考一下,javascript已經(jīng)執(zhí)行到了第100個請求,而第1個請求才得到回復(fù),而第一個請求的棧信息沒有丟失,說明第一個請求的請求棧信息被記錄了,這一過程便是注冊IO事件。
從上面注冊事件后,事件循環(huán)得到激活,對于上面代碼中fs.readFile這個讀文件IO則開始真正執(zhí)行,而這時候IO的執(zhí)行跟javascript代碼的執(zhí)行便沒有關(guān)系了,由nodejs底層libuv提供的線程池接收該文件IO執(zhí)行工作,該線程池默認(rèn)大小為4,可以通過環(huán)境變量process.env.UV_THREADPOOL_SIZE在啟動的時候進(jìn)行調(diào)整,但是最大不能超過1024個,有興趣的可以查看線程池源碼;由上可以看出nodejs內(nèi)部實(shí)際是多進(jìn)程并行工作的,而是利用事件循環(huán)做了封口處理。
再來說說事件循環(huán),上面示例中fs.readFile讀文件時,如何知道這個讀操作完成了呢?可以思考一下,讀操作是線程池來控制執(zhí)行的,在該線程執(zhí)行前,先在注冊事件的內(nèi)存中初始化一個狀態(tài)是“執(zhí)行中”,并且事件循環(huán)也已經(jīng)被激活,開始輪詢等待執(zhí)行結(jié)果,當(dāng)執(zhí)行IO的線程在執(zhí)行完之后,再通過底層的異步IO接口(epoll_wait/IOCP)進(jìn)行通知到初始注冊的任務(wù)隊列內(nèi)存進(jìn)行變更狀態(tài),事件循環(huán)輪詢到狀態(tài)變成“已完成”,這時候在IO事件注冊時注入的回調(diào)函數(shù)得到執(zhí)行權(quán),javascript線程開始工作,整個異步過程完畢。
可以看看事件循環(huán)里面都要經(jīng)過哪些步驟,如何稱為事件循環(huán)。
可以看一下英文原版的解釋,事件循環(huán)解釋
翻譯過來:
**階段概覽**timers:這個階段執(zhí)行setTimeout() 和 setInterval()中到期的回調(diào)函數(shù)
I/O callbacks:執(zhí)行所有除了setTimeout() ,setInterval(),close事件,setImmediate的其他回調(diào)函數(shù)
idle, prepare:僅內(nèi)部使用
poll:獲取新的I/O 事件,在適當(dāng)?shù)臈l件下nodejs會阻塞在這個階段
check:setImmediate的回調(diào)函數(shù)在這里被調(diào)用
close callbacks:像socket.on("close",func)這一類執(zhí)行close事件的回調(diào)
如上內(nèi)容均為自己總結(jié),難免會有錯誤或者認(rèn)識偏差,如有問題,希望大家留言指正,以免誤人,若有什么問題請留言,會盡力回答之。如果對你有幫助不要忘了分享給你的朋友或者點(diǎn)擊右下方的“在看”哦!也可以關(guān)注作者,查看歷史文章并且關(guān)注最新動態(tài),助你早日成為一名全棧工程師!
總結(jié)
以上是生活随笔為你收集整理的nodejs 服务器怎么导入qs_nodejs基本原理总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 组合筛选vue_Vue 3 组合式API
- 下一篇: z390 黑苹果启动盘_不到800元买块