gpt4 book ai didi

node.js - node.js 中的多线程请求处理(部署在 Kubernetes 和 Nginx 后面)

转载 作者:行者123 更新时间:2023-12-02 11:34:27 25 4
gpt4 key购买 nike

我有一个单线程、基于 Web 的 CPU 密集型工作负载,实现为 Node.js 服务器(快速)并部署在 Kubernetes 上,没有 CPU 请求/限制(尽力而为)。在四核物理机上执行此工作负载平均需要约 700-800 毫秒。服务器位于 Nginx 负载均衡器后面(均采用默认配置)。简而言之,工作量简单如下:

for (let $i = 0; $i < 100; $i++) {
const prime_length = 100;
const diffHell = crypto.createDiffieHellman(prime_length);
const key = diffHell.generateKeys('base64');
checksum(key);
}
我的 Express app.js 中有一个事件处理程序,它在接收或发送请求时在控制台中记录时间戳,如下所示:
app.use((req, res, next) => {
const start = process.hrtime();
console.log(`Received ${req.method} ${req.originalUrl} from ${req.headers['referer']} at {${now()}} [RECEIVED]`)

res.on('close', () => {
const durationInMilliseconds = helper.getDurationInMilliseconds(start);
console.log(`Closed received ${req.method} ${req.originalUrl} from ${req.headers['referer']} {${now()}} [CLOSED] ${durationInMilliseconds.toLocaleString()} ms`)
});
next();
})
我同时从 3 台不同的物理机向该服务发送 3 个并行请求。所有这些服务器,加上所有 kubernetes Node 都启用了 NTP,并且它们的本地时间同步在一起。
为了运行流量,我在单独的 screen 中 ssh 到所有这 3 个服务器(使用linux的屏幕),准备 curl在命令行中输入命令,然后使用以下命令发送并输入以同时运行所有流量:
screen -S 12818.3 -X stuff "
" & screen -S 12783.2 -X stuff "
" & screen -S 12713.1 -X stuff "
"
从日志中,我可以看到所有 3 个请求同时发送:在 17:26:37.888
有趣的是,服务器在完成下一个请求后立即收到每个请求:
  • 请求 1 在 17:26:37.922040382 收到,需要 740.128 毫秒
    流程
  • 请求 2 在 17:26:38.663390107 收到,需要 724.524 毫秒
    流程
  • 请求 3 在 17:26:39.388508923 收到,需要 695.894 毫秒
    流程

  • 这是容器中生成的日志(使用 kubectl logs -l name=s1 --tail=9999999999 --timestamps 提取):
    2020-10-11T17:26:37.922040382Z Received GET /s1/cpu/100 from undefined at {1602429997921393902} [RECEIVED]
    2020-10-11T17:26:38.662193765Z Closed received GET /s1/cpu/100 from undefined {1602429998661523611} [CLOSED] 740.128 ms
    2020-10-11T17:26:38.663390107Z Received GET /s1/cpu/100 from undefined at {1602429998662810195} [RECEIVED]
    2020-10-11T17:26:39.387987847Z Closed received GET /s1/cpu/100 from undefined {1602429999387339320} [CLOSED] 724.524 ms
    2020-10-11T17:26:39.388508923Z Received GET /s1/cpu/100 from undefined at {1602429999387912718} [RECEIVED]
    2020-10-11T17:26:40.084479697Z Closed received GET /s1/cpu/100 from undefined {1602430000083806321} [CLOSED] 695.894 ms
    我检查了 CPU 使用率,同时使用了 htoppidstat ,奇怪的是一直只有一个核心被使用......
    我期待 node.js 服务器同时接收所有请求并在不同的线程中处理它们(通过生成新线程),但似乎并非如此。如何让 node.js 并行处理请求,并利用它拥有的所有内核?
    这是我的完整代码:
    var express = require('express');
    const crypto = require('crypto');
    const now = require('nano-time');

    var app = express();
    function checksum(str, algorithm, encoding) {
    return crypto
    .createHash(algorithm || 'md5')
    .update(str, 'utf8')
    .digest(encoding || 'hex');
    }

    function getDurationInMilliseconds (start) {
    const NS_PER_SEC = 1e9;
    const NS_TO_MS = 1e6;
    const diff = process.hrtime(start);

    return (diff[0] * NS_PER_SEC + diff[1]) / NS_TO_MS;
    }

    app.use((req, res, next) => {
    const start = process.hrtime();
    console.log(`Received ${req.method} ${req.originalUrl} from ${req.headers['referer']} at {${now()}} [RECEIVED]`)

    res.on('close', () => {
    const durationInMilliseconds = getDurationInMilliseconds(start);
    console.log(`Closed received ${req.method} ${req.originalUrl} from ${req.headers['referer']} {${now()}} [CLOSED] ${durationInMilliseconds.toLocaleString()} ms`)
    });
    next();
    })

    app.all('*/cpu', (req, res) => {
    for (let $i = 0; $i < 100; $i++) {
    const prime_length = 100;
    const diffHell = crypto.createDiffieHellman(prime_length);
    const key = diffHell.generateKeys('base64');
    checksum(key);
    }
    res.send("Executed 100 Diffie-Hellman checksums in 1 thread(s)!");
    });

    module.exports = app;

    app.listen(9121)

    最佳答案

    I was expecting that the node.js server receives all requests at the same time and handles them in different threads (by generating new threads), but it seems it's not the case. How can I make node.js handle requests in parallel, and utilize all the cores it has?


    根据设计,node.js 仅在单个线程中运行您的 Javascript。我将其他线程用于某些事情,例如具有异步调用接口(interface)或磁盘 I/O 的内置加密操作,但是您用纯 Javascript 编写的任何内容都只能在单个线程中运行。对于 CPU 密集型 Javascript 代码,您需要专门更改代码的设计,以便使用多个 CPU 来处理该 CPU 密集型代码。
    您的选择是使用 child processesWorkerThreads .您可能想要做的是设置一组工作线程(可能每个 CPU 内核一个),然后为应该由工作线程处理的作业创建一个队列。然后,在将作业插入队列时,您会查看是否有可用的工作线程,如果有,则立即将作业发送到工作线程。如果没有,您将等到工作线程通知您它已完成并可用于下一个作业。
    在 node.js 中,WorkerThreads 是完全独立的 V8 Javascript 引擎实例,您可以在工作线程和主进程之间使用消息。

    关于node.js - node.js 中的多线程请求处理(部署在 Kubernetes 和 Nginx 后面),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64305870/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com