簡體   English   中英

阻塞請求不在 PM2 上同時運行

[英]Blocking requests not running simultaneously on PM2

在我的快速應用程序中,我在我的應用程序中定義了 2 個端點。 一種用於 is-sever-up 檢查,另一種用於模擬阻塞操作。

app.use('/status', (req, res) => {
    res.sendStatus(200);
});

app.use('/p', (req, res) => {
    const { logger } = req;
    logger.info({ message: 'Start' });
    let i = 0;
    const max = 10 ** 10;
    while (i < max) {
        i += 1;
    }
    res.send(`${i}`);
    logger.info({ message: 'End' });
});

我使用winston進行日志記錄,使用 PM2 進行集群,使用以下命令

$ pm2 start bin/httpServer.js -i 0

它已經啟動了 4 個實例。

現在,當我在不同的選項卡中按順序訪問路由/p/p/status時,在(請求 1 和請求 2)和(請求 2 和請求 3)之間有大約 1 秒的延遲,我希望得到請求 1 的響應並在一段時間后請求 2,但延遲大約 1 秒,請求 3 的響應應該立即出現。

實際:請求 3 的響應確實立即出現,但是請求 1 和請求 2 發生了一些奇怪的事情。請求 2 甚至直到請求 1 完成才開始。 這是我得到的日志。 您可以看到請求 1 結束和請求 2 開始的時間戳。

{"message":"Start","requestId":"5c1f85bd-94d9-4333-8a87-30f3b3885d9c","level":"info","timestamp":"2020-12-28 07:34:48"}
{"message":"End","requestId":"5c1f85bd-94d9-4333-8a87-30f3b3885d9c","level":"info","timestamp":"2020-12-28 07:35:03"}
{"message":"Start","requestId":"f1f86f68-1ddf-47b1-ae62-f75c7aa7a58d","level":"info","timestamp":"2020-12-28 07:35:03"}
{"message":"End","requestId":"f1f86f68-1ddf-47b1-ae62-f75c7aa7a58d","level":"info","timestamp":"2020-12-28 07:35:17"}

為什么請求 1 和請求 2 沒有同時啟動(當然延遲 1 秒)? 如果它們是同步運行的,為什么請求 3 會立即響應,而不是等待請求 1 和請求 2 完成?

這是因為 header 的連接在您的節點服務器默認響應的響應中keep-alive狀態。 因此,當您使用瀏覽器時,連接將被重用(curl 也可以模擬重用連接的情況)。 這意味着多個請求在指定時間內由同一個實例提供服務。 即使您有多個節點實例。

注意:您可以在響應中看到指定的時間 header 像這樣Keep-Alive: timeout=5如果您使用瀏覽器,請打開網絡選項卡以查看響應標頭。
如果您使用 curl,請添加-v選項以查看響應標頭

您可以嘗試在終端中同時使用多個單獨的curl命令 單獨curl命令意味着連接不會被重用。 因此,您將獲得預期的結果。 您可以在/status路由器中添加一個console.log("status test") 然后,使用pm2 logs查看哪個實例服務於請求,如下格式(這些日志是通過使用瀏覽器訪問端點產生的)。

0|server  | status test
0|server  | status test

0 表示第一個實例,當您使用瀏覽器訪問端點時,您將看到這是所有相同的實例來服務請求。 但是,如果你使用curl ,你會發現這個數字總是改變的,這意味着每個請求都由不同的節點實例提供服務。

您可以看到我在終端中使用 curl 同時發送了兩個請求。 然后,不同的節點實例來服務請求。 因此, console.log的開始和結束時間是相同的。 在這個例子中,我有 8 個事件循環,所以我可以同時處理 8 個長處理(同步代碼)請求。

在此處輸入圖像描述

而且,您可以使用curl來模擬keep-alive情況。 然后,您會看到請求由同一個節點實例提供服務。

curl http://localhost:8080/status http://localhost:8080/status -v -H "Connection: keep-alive"

您還可以使用connection close來查看請求由不同的節點實例提供服務。

curl http://localhost:8080/status http://localhost:8080/status -v -H "Connection: close"

你可以在這里看到不同之處。

在此處輸入圖像描述

如果要關閉服務器端的連接,可以使用以下代碼。

res.setHeader("Connection", "close")

這是我的測試代碼。

const express = require("express")
const app = express();
const port = 8080;

app.use('/status', (req, res) => {
    console.log("status tests");
    res.sendStatus(200);
});

app.use('/p', (req, res) => {
    console.log(new Date() + " start");
    let i = 0;
    const max = 10 ** 10;
    while (i < max) {
        i += 1;
    }
    res.send(`${i}`);
    console.log(new Date() + " end");
});

app.listen(port, () => {
    return console.log(`server is listening on ${port}`);
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM