• 
    

      <address id="upfr9"><pre id="upfr9"><strike id="upfr9"></strike></pre></address>
      1. <address id="upfr9"><tr id="upfr9"></tr></address><dl id="upfr9"></dl>

        Node高并發(fā)的原理是什么

        這篇文章主要介紹“Node高并發(fā)的原理是什么”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Node高并發(fā)的原理是什么”文章能幫助大家解決問題。

        成都創(chuàng)新互聯(lián)成都網(wǎng)站建設定制網(wǎng)站開發(fā),是成都網(wǎng)站設計公司,為活動板房提供網(wǎng)站建設服務,有成熟的網(wǎng)站定制合作流程,提供網(wǎng)站定制設計服務:原型圖制作、網(wǎng)站創(chuàng)意設計、前端HTML5制作、后臺程序開發(fā)等。成都網(wǎng)站維護熱線:028-86922220

        從頭聊起

        一個常見web應用會做哪些事情

        • 運算(執(zhí)行業(yè)務邏輯、數(shù)學運算、函數(shù)調用等。主要工作在CPU進行)

        • I/O(如讀寫文件、讀寫數(shù)據(jù)庫、讀寫網(wǎng)絡請求等。主要工作在各種I/O設備,如磁盤、網(wǎng)卡等)

        一個典型的傳統(tǒng)web應用實現(xiàn)

        • 多進程,一個請求fork一個(子)進程 + 阻塞I/O(即blocking I/O或BIO)

        • 多線程,一個請求創(chuàng)建一個線程 + 阻塞I/O


        多進程web應用示例偽代碼

        listenFd = new Socket(); // 創(chuàng)建監(jiān)聽socket
        Bind(listenFd, 80); // 綁定端口
        Listen(listenFd);   // 開始監(jiān)聽
        
        for ( ; ; ) {
            // 接收客戶端請求,通過新的socket建立連接
            connFd = Accept(listenFd);
            // fork子進程
            if ((pid = Fork()) === 0) {
                // 子進程中
                // BIO讀取網(wǎng)絡請求數(shù)據(jù),阻塞,發(fā)生進程調度
                request = connFd.read();
                // BIO讀取本地文件,阻塞,發(fā)生進程調度
                content = ReadFile('test.txt');
                // 將文件內容寫入響應
                Response.write(content);
            }
        }

        多線程應用實際上和多進程類似,只不過將一個請求分配一個進程換成了一個請求分配一個線程。線程對比進程更輕量,在系統(tǒng)資源占用上更少,上下文切換(ps:所謂上下文切換,稍微解釋一下:單核心CPU的情況下同一時間只能執(zhí)行一個進程或線程中的任務,而為了宏觀上的并行,則需要在多個進程或線程之間按時間片來回切換以保證各進、線程都有機會被執(zhí)行)的開銷也更??;同時線程間更容易共享內存,便于開發(fā)

        上文中提到了web應用的兩個核心要點,一個是進(線)程模型,一個是I/O模型。那阻塞I/O到底是什么?又有哪些其他的I/O模型呢?別著急,首先我們看一下什么是阻塞

        什么是阻塞?什么是阻塞I/O?

        簡而言之,阻塞是指函數(shù)調用返回之前,當前進(線)程會被掛起,進入等待狀態(tài),在這個狀態(tài)下,當前進(線)程暫停運行,引起CPU的進(線)程調度。函數(shù)只有在內部工作全部執(zhí)行完成后才會返回給調用者

        所以阻塞I/O是,應用程序通過API調用I/O操作后,當前進(線)程將會進入等待狀態(tài),代碼無法繼續(xù)往下執(zhí)行,這時CPU可以進行進(線)程調度,即切換到其他可執(zhí)行的進(線)程繼續(xù)執(zhí)行,當前進(線)程在底層I/O請求處理完后才會返回并可以繼續(xù)執(zhí)行

        多進(線)程 + 阻塞I/O模型有什么問題?

        在了解了什么是阻塞和阻塞I/O后,我們來分析一下傳統(tǒng)web應用多進(線)程 + 阻塞I/O模型有什么弊端。

        因為一個請求需要分配一個進(線)程,這樣的系統(tǒng)在并發(fā)量大時需要維護大量進(線)程,且需要進行大量的上下文切換,這都需要大量的CPU、內存等系統(tǒng)資源支撐,所以在高并發(fā)請求進來時CPU和內存開銷會急劇上升,可能會迅速拖垮整個系統(tǒng)導致服務不可用

        nodejs應用實現(xiàn)

        接下來我們看看nodejs應用是如何實現(xiàn)的。

        • 事件驅動,單線程(主線程)

        • 非阻塞I/O 在官網(wǎng)上可以看到,nodejs最主要的兩大特點,一個是單線程事件驅動,一個是“非阻塞”I/O模型。單線程 + 事件驅動比較好理解,前端同學應該都很熟悉js的單線程和事件循環(huán)這套機制了,那我們主要來研究一下這個“非阻塞I/O”是怎么一回事。首先來看一段nodejs服務端應用常見的代碼,

        const net = require('net');
        const server = net.createServer();
        const fs = require('fs');
        
        server.listen(80);  // 監(jiān)聽端口
        // 監(jiān)聽事件建立連接
        server.on('connection', (socket) => {
            // 監(jiān)聽事件讀取請求數(shù)據(jù)
            socket.on('data', (data) => {
            // 異步讀取本地文件
            fs.readFile('test.txt', (err, data) => {
                    // 將讀取的內容寫入響應
                    socket.write(data);
                    socket.end();
                })
            });
        });

        可以看到在nodejs中,我們可以以異步的方式去進行I/O操作,通過API調用I/O操作后會馬上返回,緊接著就可以繼續(xù)執(zhí)行其他代碼邏輯,那為什么nodejs中的I/O是“非阻塞”的呢?回答這個問題之前我們再做一些準備工作,參考nodejs進階視頻講解:進入學習

        read操作基本步驟

        首先看下一個read操作需要經(jīng)歷哪些步驟

        • 用戶程序調用I/O操作API,內部發(fā)出系統(tǒng)調用,進程從用戶態(tài)轉到內核態(tài)

        • 系統(tǒng)發(fā)出I/O請求,等待數(shù)據(jù)準備好(如網(wǎng)絡I/O,等待數(shù)據(jù)從網(wǎng)絡中到達socket;等待系統(tǒng)從磁盤上讀取數(shù)據(jù)等)

        • 數(shù)據(jù)準備好后,復制到內核緩沖區(qū)

        • 從內核空間復制到用戶空間,用戶程序拿到數(shù)據(jù)

        接下來我們看一下操作系統(tǒng)中有哪些I/O模型

        幾種I/O模型

        阻塞式I/O

        Node高并發(fā)的原理是什么


        非阻塞式I/O

        Node高并發(fā)的原理是什么


        I/O多路復用(進程可同時監(jiān)聽多個I/O設備就緒)

        Node高并發(fā)的原理是什么


        信號驅動I/O

        Node高并發(fā)的原理是什么


        異步I/O

        Node高并發(fā)的原理是什么


        那么nodejs里到底使用了哪種I/O模型呢?是上圖中的“非阻塞I/O”嗎?別著急,先接著往下看,我們來了解下nodejs的體系結構

        nodejs體系結構,線程、I/O模型分析

        Node高并發(fā)的原理是什么

        最上面一層是就是我們編寫nodejs應用代碼時可以使用的API庫,下面一層則是用來打通nodejs和它所依賴的底層庫的一個中間層,比如實現(xiàn)讓js代碼可以調用底層的c代碼庫。來到最下面一層,可以看到前端同學熟悉的V8,還有其他一些底層依賴。注意,這里有一個叫l(wèi)ibuv的庫,它是干什么的呢?從圖中也能看出,libuv幫助nodejs實現(xiàn)了底層的線程池、異步I/O等功能。libuv實際上是一個跨平臺的c語言庫,它在windows、linux等不同平臺下會調用不同的實現(xiàn)。我這里主要分析linux下libuv的實現(xiàn),因為我們的應用大部分時候還是運行在linux環(huán)境下的,且平臺間的差異性并不會影響我們對nodejs原理的分析和理解。好了,對于nodejs在linux下的I/O模型來說,libuv實際上提供了兩種不同場景下的不同實現(xiàn),處理網(wǎng)絡I/O主要由epoll函數(shù)實現(xiàn)(其實就是I/O多路復用,在前面的圖中使用的是select函數(shù)來實現(xiàn)I/O多路復用,而epoll可以理解為select函數(shù)的升級版,這個暫時不做具體分析),而處理文件I/O則由多線程(線程池) + 阻塞I/O模擬異步I/O實現(xiàn)


        下面是一段我寫的nodejs底層實現(xiàn)的偽代碼幫助大家理解

        listenFd = new Socket();    // 創(chuàng)建監(jiān)聽socket
        Bind(listenFd, 80); // 綁定端口
        Listen(listenFd);   // 開始監(jiān)聽
        
        for ( ; ; ) {
            // 阻塞在epoll函數(shù)上,等待網(wǎng)絡數(shù)據(jù)準備好
            // epoll可同時監(jiān)聽listenFd以及多個客戶端連接上是否有數(shù)據(jù)準備就緒
            // clients表示當前所有客戶端連接,curFd表示epoll函數(shù)最終拿到的一個就緒的連接
            curFd = Epoll(listenFd, clients);
        
            if (curFd === listenFd) {
                // 監(jiān)聽套接字收到新的客戶端連接,創(chuàng)建套接字
                int connFd = Accept(listenFd);
                // 將新建的連接添加到epoll監(jiān)聽的list
                clients.push(connFd);
            }
        
            else {
                // 某個客戶端連接數(shù)據(jù)就緒,讀取請求數(shù)據(jù)
                request = curFd.read();
                // 這里拿到請求數(shù)據(jù)后可以發(fā)出data事件進入nodejs的事件循環(huán)
                ...
            }
        }
        
        // 讀取本地文件時,libuv用多線程(線程池) + BIO模擬異步I/O
        ThreadPool.run((callback) => {
            // 在線程里用BIO讀取文件
            String content = Read('text.txt');  
            // 發(fā)出事件調用nodejs提供的callback
        });

        通過I/O多路復用 + 多線程模擬的異步I/O配合事件循環(huán)機制,nodejs就實現(xiàn)了單線程處理并發(fā)請求并且不會阻塞。所以回到之前所說的“非阻塞I/O”模型,實際上nodejs并沒有直接使用通常定義上的非阻塞I/O模型,而是I/O多路復用模型 + 多線程BIO。我認為“非阻塞I/O”其實更多是對nodejs編程人員來說的一種描述,從編碼方式和代碼執(zhí)行順序上來講,nodejs的I/O調用的確是“非阻塞”的。

        關于“Node高并發(fā)的原理是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識,可以關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。

        當前名稱:Node高并發(fā)的原理是什么
        鏈接URL:http://www.jbt999.com/article16/pdggdg.html

        成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供電子商務、網(wǎng)站建設微信小程序、網(wǎng)頁設計公司、網(wǎng)站設計、App設計

        廣告

        聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:[email protected]。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

        手機網(wǎng)站建設

      2. 
        

          <address id="upfr9"><pre id="upfr9"><strike id="upfr9"></strike></pre></address>
          1. <address id="upfr9"><tr id="upfr9"></tr></address><dl id="upfr9"></dl>
            欧美美女操B视频 | 伊人久色 | 国产的色情电影在线播放 | 国产中文成人 | 亚洲高清视频不卡无码视频免费在线观看 | 色四月婷婷网五月天 | 婷婷精品国产丁香五月天麻豆 | 超碰日日夜夜 | www.亚洲黄色 | 豆花视频在线看 |