Node.js如何處理多個請求?

葡萄城技術團隊發表於2023-11-08

Node.js如何處理多個請求?

前言

在電腦科學領域,關於併發和並行的概念經常被提及。然而,這兩個術語常常被混為一談,導致很多人對它們的理解存在著很多混淆。本文小編將透過對併發和並行的深入解析,幫助讀者更好地理解它們之間的不同特點和應用場景。同時,文章還將介紹Node.js如何高效地處理多個請求的技巧和方法。

什麼是併發

併發是指兩個或多個任務可以在重疊的時間段內開始、執行和完成。這並不一定意味著它們將同時執行,但它們可以交錯執行,以便在任何給定的時間,總有一個任務在執行。

下面小編以一個簡單的例子給讀者詳細的解釋併發的特點:

假設在一個餐廳裡面,有一個服務員從1號桌的客人那裡接受了一份點單,然後這個服務員在廚房一直等待1號桌客人的飯做好,做好之後將飯端到1號桌。

這個服務員完成第一桌客人的點單後,再前往下一桌的2號客人處,接受訂單,並前往廚房等待準備完成,等飯做好後再將點餐的餐點交給客人。

看到這裡,各位讀者可能會覺得這個服務員的做法一點都不高效,他完全可以在等第一單飯的時候去第二桌點單,按照這位服務員現在的做法,他在每一單的飯做好之前的這個時間段內什麼事情都幹不了,這樣就浪費了大量的時間。

我們現在修改一下這位服務員的做法,修改後如下:

服務員將前往1號桌接受訂單並將其交給廚房,然後返回2號桌接受訂單並將其同樣交給廚房。在這種情況下,服務員不會等待訂單準備完成,而是會繼續前往下一個桌子接受訂單,直到食物準備好。當食物準備好後,服務員會為所有桌子上的客人上菜。像上述的這種情況,沒有增加執行緒(服務員)的數量,但透過縮短空閒時間來加快處理過程。同時處理多個任務,這個就是併發。

例如:你正在做飯的同時,接到一通電話,於是你接聽了電話,當聽到爐子發出警報時,你回去關掉爐子,然後再繼續接電話。

這個例子很好地展示了併發的概念。做飯的過程中,能夠同時處理來自電話和爐子的不同事件。你在不中斷一個任務的情況下,暫時切換到另一個任務,然後再回到原來的任務。這種併發的方式能夠提高效率並更好地應對多個任務的情況。(同時做兩件事,但是一次只做一件事)

什麼是並行

並行是指兩個或多個任務可以真正同時執行。為了實現這一點,這些任務必須能夠在獨立的CPU或核心上執行。同樣的,小編依然以做飯的例子給大家解釋一下什麼是並行:

例如:你正在做飯的同時,接到一通電話,你的家人接聽了電話,你繼續做飯,你和你的家人誰也不會干擾誰,兩個不同的事情發生在兩個人身上,這個就是並行。

什麼是單執行緒程式?

單執行緒程式是按照單一順序執行程式設計指令的過程。話雖如此,如果一個應用程式具有以下一組指令:

指令A

指令B

指令C

如果這組指令在單執行緒程式中執行,執行過程將如下所示:

多執行緒程式是什麼?

多執行緒程式是在多個序列中執行程式設計指令。因此,除非多個指令被分組在不同的序列中,否則指令不需要等待執行。

為什麼Node.js是單執行緒的?

Node.js是一個單執行緒的平臺。這意味著它一次只能處理一個請求。

例如:服務員從1號桌子上接訂單並將其傳給廚房,然後去2號桌子接訂單。當從2號桌子接訂單時,1號桌子的食物已經準備好了,但是服務員不能立即過去將食物送到1號桌子,服務員必須先完成1號桌子的訂單,然後將其交給廚房,然後再將準備好的餐點送到1號桌子。

Node.js Web伺服器維護一個有限的執行緒池,為客戶端請求提供服務。多個客戶端向Node.js伺服器發出多個請求。Node.js接收這些請求並將它們放入事件佇列中。Node.js伺服器有一個內部元件,稱為事件迴圈(Event Loop),它是一個無限迴圈,接收並處理請求。這個事件迴圈是單執行緒的,也就是說,事件迴圈是事件佇列的監聽器。

Node.js如何處理多個請求?

Node.js可以透過事件驅動模型輕鬆處理多個併發請求。

當客戶端傳送請求時,單個執行緒會將該請求傳送給其他人。當前執行緒不會忙於處理該請求。伺服器有工作人員為其工作。伺服器將請求傳送給工作人員,工作人員進一步將其傳送給其他伺服器並等待響應。同時,如果有另一個請求,執行緒將其傳送給另一個工作人員,並等待來自另一個伺服器的響應。

這樣,單個執行緒將始終可用於接收客戶端的請求。它不會阻塞請求。

Node.js實現多個請求的程式碼:

const http = require('http');

// 建立一個 HTTP 伺服器物件
const server = http.createServer((req, res) => {
  // 處理請求
  if (req.url === '/') {
    // 設定響應頭
    res.writeHead(200, { 'Content-Type': 'text/plain' });

    // 傳送響應資料
    res.end('Hello, World!');
  } else if (req.url === '/about') {
    // 設定響應頭
    res.writeHead(200, { 'Content-Type': 'text/plain' });

    // 傳送響應資料
    res.end('About Us');
  } else {
    // 設定響應頭
    res.writeHead(404, { 'Content-Type': 'text/plain' });

    // 傳送響應資料
    res.end('Page Not Found');
  }
});

// 監聽 3000 埠
server.listen(3000, () => {
  console.log('Server listening on port 3000');
});

總結

總的來說,Node.js在處理多個請求方面具有優勢。它利用事件驅動和非阻塞式I/O的特性,能夠高效地處理併發請求,提供快速響應和良好的可擴充套件性。同時,透過採用適當的工具和技術,可以進一步最佳化效能,控制併發量,並提高系統的可靠性和穩定性。

擴充套件連結:

從表單驅動到模型驅動,解讀低程式碼開發平臺的發展趨勢

低程式碼開發平臺是什麼?

基於分支的版本管理,幫助低程式碼從專案交付走向定製化產品開發

Redis從入門到實踐

一節課帶你搞懂資料庫事務!

Chrome開發者工具使用教程

相關文章